mongo 1.2.rc1 → 1.2.rc2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/mongo.rb +1 -1
- data/lib/mongo/collection.rb +69 -11
- data/lib/mongo/util/core_ext.rb +10 -0
- data/test/bson/bson_test.rb +6 -0
- data/test/collection_test.rb +23 -6
- data/test/db_api_test.rb +17 -13
- metadata +7 -7
data/lib/mongo.rb
CHANGED
data/lib/mongo/collection.rb
CHANGED
@@ -556,17 +556,28 @@ module Mongo
|
|
556
556
|
|
557
557
|
# Perform a group aggregation.
|
558
558
|
#
|
559
|
-
# @param [
|
560
|
-
#
|
561
|
-
#
|
562
|
-
# @
|
563
|
-
# @
|
564
|
-
# @
|
565
|
-
#
|
566
|
-
#
|
567
|
-
#
|
568
|
-
# @
|
569
|
-
|
559
|
+
# @param [Hash] opts the options for this group operation. The minimum required are :initial
|
560
|
+
# and :reduce.
|
561
|
+
#
|
562
|
+
# @option opts [Array, String, Symbol] :key (nil) Either the name of a field or a list of fields to group by (optional).
|
563
|
+
# @option opts [String, BSON::Code] :keyf (nil) A JavaScript function to be used to generate the grouping keys (optional).
|
564
|
+
# @option opts [String, BSON::Code] :cond ({}) A document specifying a query for filtering the documents over
|
565
|
+
# which the aggregation is run (optional).
|
566
|
+
# @option opts [Hash] :initial the initial value of the aggregation counter object (required).
|
567
|
+
# @option opts [String, BSON::Code] :reduce (nil) a JavaScript aggregation function (required).
|
568
|
+
# @option opts [String, BSON::Code] :finalize (nil) a JavaScript function that receives and modifies
|
569
|
+
# each of the resultant grouped objects. Available only when group is run with command
|
570
|
+
# set to true.
|
571
|
+
#
|
572
|
+
# @return [Array] the command response consisting of grouped items.
|
573
|
+
def group(key, condition={}, initial={}, reduce=nil, finalize=nil)
|
574
|
+
if key.is_a?(Hash)
|
575
|
+
return new_group(key)
|
576
|
+
else
|
577
|
+
warn "Collection#group no longer take a list of paramters. This usage is deprecated." +
|
578
|
+
"Check out the new API at http://api.mongodb.org/ruby/current/Mongo/Collection.html#group-instance_method"
|
579
|
+
end
|
580
|
+
|
570
581
|
reduce = BSON::Code.new(reduce) unless reduce.is_a?(BSON::Code)
|
571
582
|
|
572
583
|
group_command = {
|
@@ -578,6 +589,11 @@ module Mongo
|
|
578
589
|
}
|
579
590
|
}
|
580
591
|
|
592
|
+
if key.is_a?(Symbol)
|
593
|
+
raise MongoArgumentError, "Group takes either an array of fields to group by or a JavaScript function" +
|
594
|
+
"in the form of a String or BSON::Code."
|
595
|
+
end
|
596
|
+
|
581
597
|
unless key.nil?
|
582
598
|
if key.is_a? Array
|
583
599
|
key_type = "key"
|
@@ -605,6 +621,48 @@ module Mongo
|
|
605
621
|
end
|
606
622
|
end
|
607
623
|
|
624
|
+
private
|
625
|
+
|
626
|
+
def new_group(opts={})
|
627
|
+
reduce = opts[:reduce]
|
628
|
+
finalize = opts[:finalize]
|
629
|
+
cond = opts.fetch(:cond, {})
|
630
|
+
initial = opts[:initial]
|
631
|
+
|
632
|
+
if !(reduce && initial)
|
633
|
+
raise MongoArgumentError, "Group requires at minimum values for initial and reduce."
|
634
|
+
end
|
635
|
+
|
636
|
+
cmd = {
|
637
|
+
"group" => {
|
638
|
+
"ns" => @name,
|
639
|
+
"$reduce" => reduce.to_bson_code,
|
640
|
+
"cond" => cond,
|
641
|
+
"initial" => initial
|
642
|
+
}
|
643
|
+
}
|
644
|
+
|
645
|
+
if finalize
|
646
|
+
cmd['group']['finalize'] = finalize.to_bson_code
|
647
|
+
end
|
648
|
+
|
649
|
+
if key = opts[:key]
|
650
|
+
if key.is_a?(String) || key.is_a?(Symbol)
|
651
|
+
key = [key]
|
652
|
+
end
|
653
|
+
key_value = {}
|
654
|
+
key.each { |k| key_value[k] = 1 }
|
655
|
+
cmd["group"]["key"] = key_value
|
656
|
+
elsif keyf = opts[:keyf]
|
657
|
+
cmd["group"]["$keyf"] = keyf.to_bson_code
|
658
|
+
end
|
659
|
+
|
660
|
+
result = @db.command(cmd)
|
661
|
+
result["retval"]
|
662
|
+
end
|
663
|
+
|
664
|
+
public
|
665
|
+
|
608
666
|
# Return a list of distinct values for +key+ across all
|
609
667
|
# documents in the collection. The key may use dot notation
|
610
668
|
# to reach into an embedded object.
|
data/lib/mongo/util/core_ext.rb
CHANGED
data/test/bson/bson_test.rb
CHANGED
@@ -150,6 +150,12 @@ class BSONTest < Test::Unit::TestCase
|
|
150
150
|
assert_doc_pass(doc)
|
151
151
|
end
|
152
152
|
|
153
|
+
def test_code_with_symbol
|
154
|
+
assert_raise_error ArgumentError, "BSON::Code must be in the form of a String" do
|
155
|
+
Code.new(:fubar)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
153
159
|
def test_code_with_scope
|
154
160
|
doc = {'$where' => Code.new('this.a.b < this.b', {'foo' => 1})}
|
155
161
|
assert_doc_pass(doc)
|
data/test/collection_test.rb
CHANGED
@@ -626,15 +626,25 @@ class TestCollection < Test::Unit::TestCase
|
|
626
626
|
@reduce_function = "function (obj, prev) { prev.count += inc_value; }"
|
627
627
|
end
|
628
628
|
|
629
|
+
should "fail if missing required options" do
|
630
|
+
assert_raise MongoArgumentError do
|
631
|
+
@@test.group(:initial => {})
|
632
|
+
end
|
633
|
+
|
634
|
+
assert_raise MongoArgumentError do
|
635
|
+
@@test.group(:reduce => "foo")
|
636
|
+
end
|
637
|
+
end
|
638
|
+
|
629
639
|
should "group results using eval form" do
|
630
|
-
assert_equal 1, @@test.group(
|
631
|
-
assert_equal 2, @@test.group(
|
632
|
-
assert_equal 4, @@test.group(
|
640
|
+
assert_equal 1, @@test.group(:initial => @initial, :reduce => Code.new(@reduce_function, {"inc_value" => 0.5}))[0]["count"]
|
641
|
+
assert_equal 2, @@test.group(:initial => @initial, :reduce => Code.new(@reduce_function, {"inc_value" => 1}))[0]["count"]
|
642
|
+
assert_equal 4, @@test.group(:initial => @initial, :reduce => Code.new(@reduce_function, {"inc_value" => 2}))[0]["count"]
|
633
643
|
end
|
634
644
|
|
635
645
|
should "finalize grouped results" do
|
636
646
|
@finalize = "function(doc) {doc.f = doc.count + 200; }"
|
637
|
-
assert_equal 202, @@test.group(
|
647
|
+
assert_equal 202, @@test.group(:initial => @initial, :reduce => Code.new(@reduce_function, {"inc_value" => 1}), :finalize => @finalize)[0]["f"]
|
638
648
|
end
|
639
649
|
end
|
640
650
|
|
@@ -650,7 +660,7 @@ class TestCollection < Test::Unit::TestCase
|
|
650
660
|
end
|
651
661
|
|
652
662
|
should "group" do
|
653
|
-
result = @@test.group(
|
663
|
+
result = @@test.group(:key => :a, :initial => @initial, :reduce => @reduce_function)
|
654
664
|
assert result.all? { |r| r['count'] == 200 }
|
655
665
|
end
|
656
666
|
end
|
@@ -669,10 +679,17 @@ class TestCollection < Test::Unit::TestCase
|
|
669
679
|
end
|
670
680
|
|
671
681
|
should "group results" do
|
672
|
-
results = @@test.group(@keyf,
|
682
|
+
results = @@test.group(:keyf => @keyf, :initial => @initial, :reduce => @reduce).sort {|a, b| a['count'] <=> b['count']}
|
673
683
|
assert results[0]['even'] && results[0]['count'] == 2.0
|
674
684
|
assert results[1]['odd'] && results[1]['count'] == 3.0
|
675
685
|
end
|
686
|
+
|
687
|
+
should "group filtered results" do
|
688
|
+
results = @@test.group(:keyf => @keyf, :cond => {:a => {'$ne' => 2}},
|
689
|
+
:initial => @initial, :reduce => @reduce).sort {|a, b| a['count'] <=> b['count']}
|
690
|
+
assert results[0]['even'] && results[0]['count'] == 1.0
|
691
|
+
assert results[1]['odd'] && results[1]['count'] == 3.0
|
692
|
+
end
|
676
693
|
end
|
677
694
|
|
678
695
|
context "A collection with two records" do
|
data/test/db_api_test.rb
CHANGED
@@ -509,33 +509,37 @@ class DBAPITest < Test::Unit::TestCase
|
|
509
509
|
@@db.drop_collection("test")
|
510
510
|
test = @@db.collection("test")
|
511
511
|
|
512
|
-
assert_equal [], test.group(
|
513
|
-
assert_equal [], test.group(
|
512
|
+
assert_equal [], test.group(:initial => {"count" => 0}, :reduce => "function (obj, prev) { prev.count++; }")
|
513
|
+
assert_equal [], test.group(:initial => {"count" => 0}, :reduce => "function (obj, prev) { prev.count++; }")
|
514
514
|
|
515
515
|
test.insert("a" => 2)
|
516
516
|
test.insert("b" => 5)
|
517
517
|
test.insert("a" => 1)
|
518
518
|
|
519
|
-
assert_equal 3, test.group(
|
520
|
-
|
521
|
-
assert_equal
|
522
|
-
|
519
|
+
assert_equal 3, test.group(:initial => {"count" => 0},
|
520
|
+
:reduce => "function (obj, prev) { prev.count++; }")[0]["count"]
|
521
|
+
assert_equal 3, test.group(:initial => {"count" => 0},
|
522
|
+
:reduce => "function (obj, prev) { prev.count++; }")[0]["count"]
|
523
|
+
assert_equal 1, test.group(:cond => {"a" => {"$gt" => 1}},
|
524
|
+
:initial => {"count" => 0}, :reduce => "function (obj, prev) { prev.count++; }")[0]["count"]
|
525
|
+
assert_equal 1, test.group(:cond => {"a" => {"$gt" => 1}},
|
526
|
+
:initial => {"count" => 0}, :reduce => "function (obj, prev) { prev.count++; }")[0]["count"]
|
523
527
|
|
524
528
|
finalize = "function (obj) { obj.f = obj.count - 1; }"
|
525
|
-
assert_equal 2, test.group(
|
529
|
+
assert_equal 2, test.group(:initial => {"count" => 0},
|
530
|
+
:reduce => "function (obj, prev) { prev.count++; }", :finalize => finalize)[0]["f"]
|
526
531
|
|
527
532
|
test.insert("a" => 2, "b" => 3)
|
528
533
|
expected = [{"a" => 2, "count" => 2},
|
529
534
|
{"a" => nil, "count" => 1},
|
530
535
|
{"a" => 1, "count" => 1}]
|
531
|
-
assert_equal expected, test.group(["a"],
|
532
|
-
|
536
|
+
assert_equal expected, test.group(:key => ["a"], :initial => {"count" => 0},
|
537
|
+
:reduce => "function (obj, prev) { prev.count++; }")
|
538
|
+
assert_equal expected, test.group(:key => :a, :initial => {"count" => 0},
|
539
|
+
:reduce => "function (obj, prev) { prev.count++; }")
|
533
540
|
|
534
541
|
assert_raise OperationFailure do
|
535
|
-
test.group(
|
536
|
-
end
|
537
|
-
assert_raise OperationFailure do
|
538
|
-
test.group([], {}, {}, "5 ++ 5", true)
|
542
|
+
test.group(:initial => {}, :reduce => "5 ++ 5")
|
539
543
|
end
|
540
544
|
end
|
541
545
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15424225
|
5
5
|
prerelease: 4
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 2
|
9
9
|
- rc
|
10
|
-
-
|
11
|
-
version: 1.2.
|
10
|
+
- 2
|
11
|
+
version: 1.2.rc2
|
12
12
|
platform: ruby
|
13
13
|
authors:
|
14
14
|
- Jim Menard
|
@@ -18,7 +18,7 @@ autorequire:
|
|
18
18
|
bindir: bin
|
19
19
|
cert_chain: []
|
20
20
|
|
21
|
-
date: 2011-01-
|
21
|
+
date: 2011-01-06 00:00:00 -05:00
|
22
22
|
default_executable:
|
23
23
|
dependencies:
|
24
24
|
- !ruby/object:Gem::Dependency
|
@@ -29,13 +29,13 @@ dependencies:
|
|
29
29
|
requirements:
|
30
30
|
- - ">="
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
hash:
|
32
|
+
hash: 15424225
|
33
33
|
segments:
|
34
34
|
- 1
|
35
35
|
- 2
|
36
36
|
- rc
|
37
|
-
-
|
38
|
-
version: 1.2.
|
37
|
+
- 2
|
38
|
+
version: 1.2.rc2
|
39
39
|
type: :runtime
|
40
40
|
version_requirements: *id001
|
41
41
|
description: A Ruby driver for MongoDB. For more information about Mongo, see http://www.mongodb.org.
|