add group method on collections
This commit is contained in:
parent
2dffc4b504
commit
29cdfe64f1
|
@ -139,6 +139,48 @@ module XGen
|
||||||
@db.drop_collection(@name)
|
@db.drop_collection(@name)
|
||||||
end
|
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:
|
# Return an array of hashes, one for each index. Each hash contains:
|
||||||
#
|
#
|
||||||
# :name :: Index name
|
# :name :: Index name
|
||||||
|
|
|
@ -530,6 +530,20 @@ class DBAPITest < Test::Unit::TestCase
|
||||||
assert id != 0
|
assert id != 0
|
||||||
end
|
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"
|
# TODO this test fails with error message "Undefed Before end of object"
|
||||||
# That is a database error. The undefined type may go away.
|
# That is a database error. The undefined type may go away.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue