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.
@@ -3,7 +3,7 @@
3
3
  $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
4
 
5
5
  module Mongo
6
- VERSION = "1.2.rc1"
6
+ VERSION = "1.2.rc2"
7
7
  end
8
8
 
9
9
  module Mongo
@@ -556,17 +556,28 @@ module Mongo
556
556
 
557
557
  # Perform a group aggregation.
558
558
  #
559
- # @param [Array, String, BSON::Code, Nil] :key either 1) an array of fields to group by,
560
- # 2) a javascript function to generate the key object, or 3) nil.
561
- # @param [Hash] condition an optional document specifying a query to limit the documents over which group is run.
562
- # @param [Hash] initial initial value of the aggregation counter object
563
- # @param [String, BSON::Code] reduce aggregation function, in JavaScript
564
- # @param [String, BSON::Code] finalize :: optional. a JavaScript function that receives and modifies
565
- # each of the resultant grouped objects. Available only when group is run
566
- # with command set to true.
567
- #
568
- # @return [Array] the grouped items.
569
- def group(key, condition, initial, reduce, finalize=nil)
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.
@@ -48,3 +48,13 @@ class Hash
48
48
  end
49
49
 
50
50
  end
51
+
52
+ #:nodoc:
53
+ class String
54
+
55
+ #:nodoc:
56
+ def to_bson_code
57
+ BSON::Code.new(self)
58
+ end
59
+
60
+ end
@@ -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)
@@ -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([], {}, @initial, Code.new(@reduce_function, {"inc_value" => 0.5}))[0]["count"]
631
- assert_equal 2, @@test.group([], {}, @initial, Code.new(@reduce_function, {"inc_value" => 1}))[0]["count"]
632
- assert_equal 4, @@test.group([], {}, @initial, Code.new(@reduce_function, {"inc_value" => 2}))[0]["count"]
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([], {}, @initial, Code.new(@reduce_function, {"inc_value" => 1}), @finalize)[0]["f"]
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([:a], {}, @initial, @reduce_function, nil)
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, {}, @initial, @reduce).sort {|a, b| a['count'] <=> b['count']}
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
@@ -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([], {}, {"count" => 0}, "function (obj, prev) { prev.count++; }")
513
- assert_equal [], test.group([], {}, {"count" => 0}, "function (obj, prev) { prev.count++; }")
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([], {}, {"count" => 0}, "function (obj, prev) { prev.count++; }")[0]["count"]
520
- assert_equal 3, test.group([], {}, {"count" => 0}, "function (obj, prev) { prev.count++; }")[0]["count"]
521
- assert_equal 1, test.group([], {"a" => {"$gt" => 1}}, {"count" => 0}, "function (obj, prev) { prev.count++; }")[0]["count"]
522
- assert_equal 1, test.group([], {"a" => {"$gt" => 1}}, {"count" => 0}, "function (obj, prev) { prev.count++; }")[0]["count"]
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([], {}, {"count" => 0}, "function (obj, prev) { prev.count++; }", finalize)[0]["f"]
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"], {}, {"count" => 0}, "function (obj, prev) { prev.count++; }")
532
- assert_equal expected, test.group(["a"], {}, {"count" => 0}, "function (obj, prev) { prev.count++; }", true)
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([], {}, {}, "5 ++ 5")
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: 15424231
4
+ hash: 15424225
5
5
  prerelease: 4
6
6
  segments:
7
7
  - 1
8
8
  - 2
9
9
  - rc
10
- - 1
11
- version: 1.2.rc1
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-05 00:00:00 -05:00
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: 15424231
32
+ hash: 15424225
33
33
  segments:
34
34
  - 1
35
35
  - 2
36
36
  - rc
37
- - 1
38
- version: 1.2.rc1
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.