add group method on collections
This commit is contained in:
parent
2dffc4b504
commit
29cdfe64f1
|
@ -139,6 +139,48 @@ module XGen
|
|||
@db.drop_collection(@name)
|
||||
end
|
||||
|
||||
# Perform a query similar to an SQL group by operation.
|
||||
#
|
||||
# Returns an array of grouped items.
|
||||
#
|
||||
# :keys :: list of fields to group by
|
||||
# :condition :: specification of rows to be considered (as a 'find'
|
||||
# query specification)
|
||||
# :initial :: initial value of the aggregation counter object
|
||||
# :reduce :: aggregation function as a JavaScript string
|
||||
def group(keys, condition, initial, reduce)
|
||||
group_function = <<EOS
|
||||
function () {
|
||||
var c = db[ns].find(condition);
|
||||
var map = new Map();
|
||||
var reduce_function = #{reduce};
|
||||
while (c.hasNext()) {
|
||||
var obj = c.next();
|
||||
|
||||
var key = {};
|
||||
for (var i in keys) {
|
||||
key[keys[i]] = obj[keys[i]];
|
||||
}
|
||||
|
||||
var aggObj = map[key];
|
||||
if (aggObj == null) {
|
||||
var newObj = Object.extend({}, key);
|
||||
aggObj = map[key] = Object.extend(newObj, initial);
|
||||
}
|
||||
reduce_function(obj, aggObj);
|
||||
}
|
||||
return {"result": map.values()};
|
||||
}
|
||||
EOS
|
||||
return @db.eval(Code.new(group_function,
|
||||
{
|
||||
"ns" => @name,
|
||||
"keys" => keys,
|
||||
"condition" => condition,
|
||||
"initial" => initial
|
||||
}))["result"]
|
||||
end
|
||||
|
||||
# Return an array of hashes, one for each index. Each hash contains:
|
||||
#
|
||||
# :name :: Index name
|
||||
|
|
|
@ -530,6 +530,20 @@ class DBAPITest < Test::Unit::TestCase
|
|||
assert id != 0
|
||||
end
|
||||
|
||||
def test_group
|
||||
@@db.drop_collection("test")
|
||||
test = @@db.collection("test")
|
||||
|
||||
assert_equal [], test.group([], {}, {"count" => 0}, "function (obj, prev) { prev.count++; }")
|
||||
|
||||
test.insert("a" => 2)
|
||||
test.insert("b" => 5)
|
||||
test.insert("a" => 1)
|
||||
|
||||
assert_equal 3, test.group([], {}, {"count" => 0}, "function (obj, prev) { prev.count++; }")[0]["count"]
|
||||
assert_equal 1, test.group([], {"a" => {"$gt" => 1}}, {"count" => 0}, "function (obj, prev) { prev.count++; }")[0]["count"]
|
||||
end
|
||||
|
||||
# TODO this test fails with error message "Undefed Before end of object"
|
||||
# That is a database error. The undefined type may go away.
|
||||
|
||||
|
|
Loading…
Reference in New Issue