mongo_doc 0.4.0 → 0.4.1
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/README.textile +6 -2
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/features/indexes.feature +28 -0
- data/features/step_definitions/index_steps.rb +10 -0
- data/lib/mongo_doc/contexts/ids.rb +1 -1
- data/lib/mongo_doc/contexts/mongo.rb +30 -1
- data/lib/mongo_doc/contexts.rb +2 -2
- data/lib/mongo_doc/document.rb +2 -0
- data/lib/mongo_doc/index.rb +27 -0
- data/lib/mongo_doc.rb +1 -1
- data/lib/{mongo_doc → mongoid}/contexts/enumerable.rb +36 -13
- data/lib/mongoid/criteria.rb +2 -1
- data/mongo_doc.gemspec +8 -5
- data/spec/contexts/mongo_spec.rb +20 -0
- data/spec/contexts_spec.rb +1 -1
- data/spec/index_spec.rb +70 -0
- metadata +9 -6
- data/spec/contexts/enumerable_spec.rb +0 -274
data/README.textile
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
h1. MongoDoc
|
2
2
|
|
3
|
-
Version: Turbulence (0.4.
|
3
|
+
Version: Turbulence (0.4.1) 2010/03/17
|
4
4
|
|
5
|
-
h2. What's New in Turbulence (0.4.
|
5
|
+
h2. What's New in Turbulence (0.4.1)
|
6
6
|
|
7
7
|
API changes (@key@ and @has_*@ still supported, will be deprectated soon)
|
8
8
|
|
@@ -14,6 +14,10 @@ API changes (@key@ and @has_*@ still supported, will be deprectated soon)
|
|
14
14
|
** @embed_many@ was @has_many@
|
15
15
|
** @embed_hash@ was @has_hash@
|
16
16
|
|
17
|
+
Indexing suppport
|
18
|
+
|
19
|
+
* @MongoDoc::Document.index@
|
20
|
+
|
17
21
|
h2. Notes
|
18
22
|
|
19
23
|
* 2010-03-12 Thanks to weather in ATL, cleaned up attr_accessor and switched to embed association macros
|
data/Rakefile
CHANGED
@@ -89,7 +89,7 @@ namespace :mongoid do
|
|
89
89
|
src_dir = Pathname.new('../durran-mongoid/lib/mongoid')
|
90
90
|
dest_dir = Pathname.new('lib/mongoid')
|
91
91
|
dest_dir.mkpath
|
92
|
-
%w(criteria.rb contexts/paging.rb criterion extensions/symbol/inflections.rb extensions/hash/criteria_helpers.rb matchers).each do |f|
|
92
|
+
%w(criteria.rb contexts/paging.rb contexts/enumerable.rb criterion extensions/symbol/inflections.rb extensions/hash/criteria_helpers.rb matchers).each do |f|
|
93
93
|
src = src_dir + f
|
94
94
|
if src.directory?
|
95
95
|
FileUtils.cp_r(src, dest_dir)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.4.
|
1
|
+
0.4.1
|
@@ -0,0 +1,28 @@
|
|
1
|
+
Feature: Indexes
|
2
|
+
|
3
|
+
Background:
|
4
|
+
Given an empty Contact document collection
|
5
|
+
And a Contact document named 'hashrocket' :
|
6
|
+
| Name | Type |
|
7
|
+
| Hashrocket | company |
|
8
|
+
And 'hashrocket' has interests, an array of:
|
9
|
+
| Interest |
|
10
|
+
| ruby |
|
11
|
+
| rails |
|
12
|
+
| employment |
|
13
|
+
| contract work |
|
14
|
+
| restaurants |
|
15
|
+
| hotels |
|
16
|
+
| flights |
|
17
|
+
| car rentals |
|
18
|
+
And 'hashrocket' has many addresses :
|
19
|
+
| Street | City | State | Zip Code |
|
20
|
+
| 320 First Street North | Jacksonville Beach | FL | 32250 |
|
21
|
+
| 1 Lake Michigan Street | Chicago | IL | 60611 |
|
22
|
+
| 1 Main Street | Santiago | Chile | |
|
23
|
+
And I save the document 'hashrocket'
|
24
|
+
|
25
|
+
Scenario: Simple index
|
26
|
+
When I create an index named name on the Contact collection
|
27
|
+
Then there is an index on name on the Contact collection
|
28
|
+
|
@@ -0,0 +1,10 @@
|
|
1
|
+
When /^I create an index named (.*) on the (.*) collection$/ do |index_name, doc|
|
2
|
+
klass = doc.constantize
|
3
|
+
klass.index(index_name)
|
4
|
+
end
|
5
|
+
|
6
|
+
Then /^there is an index on (.*) on the (.*) collection$/ do |index_name, doc|
|
7
|
+
klass = doc.constantize
|
8
|
+
klass.collection.index_information.should include("#{index_name}_1")
|
9
|
+
end
|
10
|
+
|
@@ -2,7 +2,7 @@ module MongoDoc
|
|
2
2
|
module Contexts
|
3
3
|
class Mongo
|
4
4
|
include Mongoid::Contexts::Paging
|
5
|
-
include
|
5
|
+
include Mongoid::Contexts::Ids
|
6
6
|
|
7
7
|
attr_reader :criteria, :cache
|
8
8
|
|
@@ -26,6 +26,25 @@ module MongoDoc
|
|
26
26
|
collection.group(options[:fields], selector, { :count => 0 }, AGGREGATE_REDUCE, true)
|
27
27
|
end
|
28
28
|
|
29
|
+
# Get the average value for the supplied field.
|
30
|
+
#
|
31
|
+
# This will take the internally built selector and options
|
32
|
+
# and pass them on to the Ruby driver's +group()+ method on the collection. The
|
33
|
+
# collection itself will be retrieved from the class provided, and once the
|
34
|
+
# query has returned it will provided a grouping of keys with averages.
|
35
|
+
#
|
36
|
+
# Example:
|
37
|
+
#
|
38
|
+
# <tt>context.avg(:age)</tt>
|
39
|
+
#
|
40
|
+
# Returns:
|
41
|
+
#
|
42
|
+
# A numeric value that is the average.
|
43
|
+
def avg(field)
|
44
|
+
total = sum(field)
|
45
|
+
total ? (total / count) : nil
|
46
|
+
end
|
47
|
+
|
29
48
|
# Get the count of matching documents in the database for the context.
|
30
49
|
#
|
31
50
|
# Example:
|
@@ -39,6 +58,16 @@ module MongoDoc
|
|
39
58
|
@count ||= collection.find(selector, options).count
|
40
59
|
end
|
41
60
|
|
61
|
+
# Gets an array of distinct values for the supplied field across the
|
62
|
+
# entire collection or the susbset given the criteria.
|
63
|
+
#
|
64
|
+
# Example:
|
65
|
+
#
|
66
|
+
# <tt>context.distinct(:title)</tt>
|
67
|
+
def distinct(field)
|
68
|
+
collection.distinct(field, selector)
|
69
|
+
end
|
70
|
+
|
42
71
|
# Determine if the context is empty or blank given the criteria. Will
|
43
72
|
# perform a quick find_one asking only for the id.
|
44
73
|
#
|
data/lib/mongo_doc/contexts.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require "mongoid/contexts/paging"
|
3
3
|
require "mongo_doc/contexts/ids"
|
4
|
-
require "
|
4
|
+
require "mongoid/contexts/enumerable"
|
5
5
|
require "mongo_doc/contexts/mongo"
|
6
6
|
|
7
7
|
module Mongoid
|
@@ -19,7 +19,7 @@ module Mongoid
|
|
19
19
|
# <tt>Contexts.context_for(criteria)</tt>
|
20
20
|
def self.context_for(criteria)
|
21
21
|
if criteria.klass.respond_to?(:_append)
|
22
|
-
return
|
22
|
+
return Mongoid::Contexts::Enumerable.new(criteria)
|
23
23
|
elsif criteria.klass.respond_to?(:collection)
|
24
24
|
return MongoDoc::Contexts::Mongo.new(criteria)
|
25
25
|
else
|
data/lib/mongo_doc/document.rb
CHANGED
@@ -4,6 +4,7 @@ require 'mongo_doc/attributes'
|
|
4
4
|
require 'mongo_doc/associations'
|
5
5
|
require 'mongo_doc/criteria'
|
6
6
|
require 'mongo_doc/finders'
|
7
|
+
require 'mongo_doc/index'
|
7
8
|
require 'mongo_doc/scope'
|
8
9
|
require 'mongo_doc/validations/macros'
|
9
10
|
|
@@ -21,6 +22,7 @@ module MongoDoc
|
|
21
22
|
extend ClassMethods
|
22
23
|
extend Criteria
|
23
24
|
extend Finders
|
25
|
+
extend Index
|
24
26
|
extend Scope
|
25
27
|
include ::Validatable
|
26
28
|
extend Validations::Macros
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module MongoDoc
|
2
|
+
module Index
|
3
|
+
|
4
|
+
# Create an index on a collection. For a unique index, pass the unique
|
5
|
+
# option +:unique => true+. For compound indexes, pass pairs of fields and
|
6
|
+
# directions (+:asc+, +:desc+) as a hash.
|
7
|
+
#
|
8
|
+
# <tt>Person.index(:last_name)</tt>
|
9
|
+
# <tt>Person.index(:ssn, :unique => true)</tt>
|
10
|
+
# <tt>Person.index(:first_name => :asc, :last_name => :asc)</tt>
|
11
|
+
# <tt>Person.index(:first_name => :asc, :last_name => :asc, :unique => true)</tt>
|
12
|
+
def index(*args)
|
13
|
+
options_and_fields = args.extract_options!
|
14
|
+
unique = options_and_fields.delete(:unique) || false
|
15
|
+
if args.any?
|
16
|
+
collection.create_index(args.first, unique)
|
17
|
+
else
|
18
|
+
collection.create_index(to_mongo_direction(options_and_fields), unique)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
protected
|
23
|
+
def to_mongo_direction(fields_hash)
|
24
|
+
fields_hash.to_a.map {|field| [field.first, field.last == :desc ? Mongo::DESCENDING : Mongo::ASCENDING]}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/mongo_doc.rb
CHANGED
@@ -1,13 +1,11 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
module
|
2
|
+
module Mongoid #:nodoc:
|
3
3
|
module Contexts #:nodoc:
|
4
4
|
class Enumerable
|
5
|
-
include
|
6
|
-
include MongoDoc::Contexts::Ids
|
7
|
-
|
5
|
+
include Ids, Paging
|
8
6
|
attr_reader :criteria
|
9
7
|
|
10
|
-
delegate :first, :last, :to => :execute
|
8
|
+
delegate :blank?, :empty?, :first, :last, :to => :execute
|
11
9
|
delegate :documents, :options, :selector, :to => :criteria
|
12
10
|
|
13
11
|
# Return aggregation counts of the grouped documents. This will count by
|
@@ -22,19 +20,33 @@ module MongoDoc #:nodoc:
|
|
22
20
|
counts
|
23
21
|
end
|
24
22
|
|
23
|
+
# Get the average value for the supplied field.
|
24
|
+
#
|
25
|
+
# Example:
|
26
|
+
#
|
27
|
+
# <tt>context.avg(:age)</tt>
|
28
|
+
#
|
29
|
+
# Returns:
|
30
|
+
#
|
31
|
+
# A numeric value that is the average.
|
32
|
+
def avg(field)
|
33
|
+
total = sum(field)
|
34
|
+
total ? (total.to_f / count) : nil
|
35
|
+
end
|
36
|
+
|
25
37
|
# Gets the number of documents in the array. Delegates to size.
|
26
38
|
def count
|
27
39
|
@count ||= documents.size
|
28
40
|
end
|
29
41
|
|
30
|
-
#
|
42
|
+
# Gets an array of distinct values for the supplied field across the
|
43
|
+
# entire array or the susbset given the criteria.
|
31
44
|
#
|
32
|
-
#
|
45
|
+
# Example:
|
33
46
|
#
|
34
|
-
#
|
35
|
-
def
|
36
|
-
|
37
|
-
documents.group_by { |doc| doc.send(field) }
|
47
|
+
# <tt>context.distinct(:title)</tt>
|
48
|
+
def distinct(field)
|
49
|
+
execute.collect { |doc| doc.send(field) }.uniq
|
38
50
|
end
|
39
51
|
|
40
52
|
# Enumerable implementation of execute. Returns matching documents for
|
@@ -47,13 +59,23 @@ module MongoDoc #:nodoc:
|
|
47
59
|
limit(documents.select { |document| document.matches?(selector) })
|
48
60
|
end
|
49
61
|
|
62
|
+
# Groups the documents by the first field supplied in the field options.
|
63
|
+
#
|
64
|
+
# Returns:
|
65
|
+
#
|
66
|
+
# A +Hash+ with field values as keys, arrays of documents as values.
|
67
|
+
def group
|
68
|
+
field = options[:fields].first
|
69
|
+
documents.group_by { |doc| doc.send(field) }
|
70
|
+
end
|
71
|
+
|
50
72
|
# Create the new enumerable context. This will need the selector and
|
51
73
|
# options from a +Criteria+ and a documents array that is the underlying
|
52
74
|
# array of embedded documents from a has many association.
|
53
75
|
#
|
54
76
|
# Example:
|
55
77
|
#
|
56
|
-
# <tt>
|
78
|
+
# <tt>Mongoid::Contexts::Enumerable.new(criteria)</tt>
|
57
79
|
def initialize(criteria)
|
58
80
|
@criteria = criteria
|
59
81
|
end
|
@@ -119,10 +141,11 @@ module MongoDoc #:nodoc:
|
|
119
141
|
skip, limit = options[:skip], options[:limit]
|
120
142
|
if skip && limit
|
121
143
|
return documents.slice(skip, limit)
|
144
|
+
elsif limit
|
145
|
+
return documents.first(limit)
|
122
146
|
end
|
123
147
|
documents
|
124
148
|
end
|
125
149
|
end
|
126
150
|
end
|
127
151
|
end
|
128
|
-
|
data/lib/mongoid/criteria.rb
CHANGED
@@ -26,13 +26,14 @@ module Mongoid #:nodoc:
|
|
26
26
|
include Enumerable
|
27
27
|
|
28
28
|
attr_reader :collection, :ids, :klass, :options, :selector
|
29
|
-
|
30
29
|
attr_accessor :documents
|
31
30
|
|
32
31
|
delegate \
|
33
32
|
:aggregate,
|
33
|
+
:avg,
|
34
34
|
:blank?,
|
35
35
|
:count,
|
36
|
+
:distinct,
|
36
37
|
:empty?,
|
37
38
|
:execute,
|
38
39
|
:first,
|
data/mongo_doc.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{mongo_doc}
|
8
|
-
s.version = "0.4.
|
8
|
+
s.version = "0.4.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Les Hill"]
|
12
|
-
s.date = %q{2010-03-
|
12
|
+
s.date = %q{2010-03-17}
|
13
13
|
s.description = %q{ODM for MongoDB}
|
14
14
|
s.email = %q{leshill@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -30,6 +30,7 @@ Gem::Specification.new do |s|
|
|
30
30
|
"examples/simple_object.rb",
|
31
31
|
"features/collections.feature",
|
32
32
|
"features/finders.feature",
|
33
|
+
"features/indexes.feature",
|
33
34
|
"features/mongodb.yml",
|
34
35
|
"features/mongodoc_base.feature",
|
35
36
|
"features/new_record.feature",
|
@@ -41,6 +42,7 @@ Gem::Specification.new do |s|
|
|
41
42
|
"features/step_definitions/document_steps.rb",
|
42
43
|
"features/step_definitions/documents.rb",
|
43
44
|
"features/step_definitions/finder_steps.rb",
|
45
|
+
"features/step_definitions/index_steps.rb",
|
44
46
|
"features/step_definitions/json_steps.rb",
|
45
47
|
"features/step_definitions/object_steps.rb",
|
46
48
|
"features/step_definitions/objects.rb",
|
@@ -64,7 +66,6 @@ Gem::Specification.new do |s|
|
|
64
66
|
"lib/mongo_doc/collection.rb",
|
65
67
|
"lib/mongo_doc/connection.rb",
|
66
68
|
"lib/mongo_doc/contexts.rb",
|
67
|
-
"lib/mongo_doc/contexts/enumerable.rb",
|
68
69
|
"lib/mongo_doc/contexts/ids.rb",
|
69
70
|
"lib/mongo_doc/contexts/mongo.rb",
|
70
71
|
"lib/mongo_doc/criteria.rb",
|
@@ -87,11 +88,13 @@ Gem::Specification.new do |s|
|
|
87
88
|
"lib/mongo_doc/ext/symbol.rb",
|
88
89
|
"lib/mongo_doc/ext/time.rb",
|
89
90
|
"lib/mongo_doc/finders.rb",
|
91
|
+
"lib/mongo_doc/index.rb",
|
90
92
|
"lib/mongo_doc/matchers.rb",
|
91
93
|
"lib/mongo_doc/query.rb",
|
92
94
|
"lib/mongo_doc/scope.rb",
|
93
95
|
"lib/mongo_doc/validations/macros.rb",
|
94
96
|
"lib/mongo_doc/validations/validates_embedded.rb",
|
97
|
+
"lib/mongoid/contexts/enumerable.rb",
|
95
98
|
"lib/mongoid/contexts/paging.rb",
|
96
99
|
"lib/mongoid/criteria.rb",
|
97
100
|
"lib/mongoid/criterion/complex.rb",
|
@@ -127,7 +130,6 @@ Gem::Specification.new do |s|
|
|
127
130
|
"spec/bson_spec.rb",
|
128
131
|
"spec/collection_spec.rb",
|
129
132
|
"spec/connection_spec.rb",
|
130
|
-
"spec/contexts/enumerable_spec.rb",
|
131
133
|
"spec/contexts/ids_spec.rb",
|
132
134
|
"spec/contexts/mongo_spec.rb",
|
133
135
|
"spec/contexts_spec.rb",
|
@@ -139,6 +141,7 @@ Gem::Specification.new do |s|
|
|
139
141
|
"spec/ext_spec.rb",
|
140
142
|
"spec/finders_spec.rb",
|
141
143
|
"spec/hash_matchers.rb",
|
144
|
+
"spec/index_spec.rb",
|
142
145
|
"spec/matchers_spec.rb",
|
143
146
|
"spec/mongodb.yml",
|
144
147
|
"spec/mongodb_pairs.yml",
|
@@ -164,7 +167,6 @@ Gem::Specification.new do |s|
|
|
164
167
|
"spec/bson_spec.rb",
|
165
168
|
"spec/collection_spec.rb",
|
166
169
|
"spec/connection_spec.rb",
|
167
|
-
"spec/contexts/enumerable_spec.rb",
|
168
170
|
"spec/contexts/ids_spec.rb",
|
169
171
|
"spec/contexts/mongo_spec.rb",
|
170
172
|
"spec/contexts_spec.rb",
|
@@ -176,6 +178,7 @@ Gem::Specification.new do |s|
|
|
176
178
|
"spec/ext_spec.rb",
|
177
179
|
"spec/finders_spec.rb",
|
178
180
|
"spec/hash_matchers.rb",
|
181
|
+
"spec/index_spec.rb",
|
179
182
|
"spec/matchers_spec.rb",
|
180
183
|
"spec/new_record_spec.rb",
|
181
184
|
"spec/query_spec.rb",
|
data/spec/contexts/mongo_spec.rb
CHANGED
@@ -39,6 +39,19 @@ describe "MongoDoc::Contexts::Mongo" do
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
+
context "#avg" do
|
43
|
+
it "is the sum/count" do
|
44
|
+
context.should_receive(:count).and_return(1)
|
45
|
+
context.should_receive(:sum).with(:field_name).and_return(1)
|
46
|
+
context.avg(:field_name)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "returns nil if there is no sum" do
|
50
|
+
context.stub(:sum).and_return(nil)
|
51
|
+
context.avg(:field_name).should be_nil
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
42
55
|
context "#count" do
|
43
56
|
it "uses find and count" do
|
44
57
|
result = stub('result')
|
@@ -48,6 +61,13 @@ describe "MongoDoc::Contexts::Mongo" do
|
|
48
61
|
end
|
49
62
|
end
|
50
63
|
|
64
|
+
context "#distinct" do
|
65
|
+
it "uses distinct" do
|
66
|
+
collection.should_receive(:distinct).with(:field_name, {})
|
67
|
+
context.distinct(:field_name)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
51
71
|
context "#execute" do
|
52
72
|
it "uses find" do
|
53
73
|
collection.should_receive(:find)
|
data/spec/contexts_spec.rb
CHANGED
@@ -24,7 +24,7 @@ describe MongoDoc::Contexts do
|
|
24
24
|
let(:klass) { ContextTest.new.children }
|
25
25
|
|
26
26
|
it "creates an Enumerable context" do
|
27
|
-
|
27
|
+
Mongoid::Contexts::Enumerable.should_receive(:new).with(criteria)
|
28
28
|
Mongoid::Contexts.context_for(criteria)
|
29
29
|
end
|
30
30
|
end
|
data/spec/index_spec.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
require "spec_helper.rb"
|
2
|
+
|
3
|
+
describe MongoDoc::Index do
|
4
|
+
class Address
|
5
|
+
include MongoDoc::Document
|
6
|
+
|
7
|
+
attr_accessor :state
|
8
|
+
end
|
9
|
+
|
10
|
+
class IndexTest
|
11
|
+
include MongoDoc::Document
|
12
|
+
|
13
|
+
attr_accessor :ssn
|
14
|
+
attr_accessor :first_name
|
15
|
+
attr_accessor :last_name
|
16
|
+
attr_accessor :birthdate, :type => Date
|
17
|
+
attr_accessor :notes
|
18
|
+
|
19
|
+
embed :addresses
|
20
|
+
|
21
|
+
# This is the API we are testing, commented out to avoid firing before
|
22
|
+
# specs are run
|
23
|
+
#
|
24
|
+
# index :birthdate
|
25
|
+
# index :ssn, :unique => true
|
26
|
+
# index :first_name => :asc, :last_name => :asc
|
27
|
+
# index :last_name => :asc, :first_name => :asc, :unique => true
|
28
|
+
# index "addresses.state"
|
29
|
+
end
|
30
|
+
|
31
|
+
let(:collection) { stub('collection') }
|
32
|
+
|
33
|
+
before do
|
34
|
+
IndexTest.stub(:collection).and_return(collection)
|
35
|
+
end
|
36
|
+
|
37
|
+
context "Simple index" do
|
38
|
+
|
39
|
+
it "creates an index for the field" do
|
40
|
+
collection.should_receive(:create_index).with(:birthdate, false)
|
41
|
+
IndexTest.index(:birthdate)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "creates a unique index for the field" do
|
45
|
+
collection.should_receive(:create_index).with(:birthdate, true)
|
46
|
+
IndexTest.index(:birthdate, :unique => true)
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
context "Compound index" do
|
52
|
+
|
53
|
+
it "creates a compound index" do
|
54
|
+
collection.should_receive(:create_index).with([[:first_name, Mongo::ASCENDING], [:last_name, Mongo::ASCENDING]], false)
|
55
|
+
IndexTest.index(:first_name => :asc, :last_name => :asc)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "creates a unique compound index" do
|
59
|
+
collection.should_receive(:create_index).with([[:first_name, Mongo::ASCENDING], [:last_name, Mongo::ASCENDING]], true)
|
60
|
+
IndexTest.index(:first_name => :asc, :last_name => :asc, :unique => true)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context "Nested index" do
|
65
|
+
it "creates an index for the field" do
|
66
|
+
collection.should_receive(:create_index).with("addresses.state", false)
|
67
|
+
IndexTest.index("addresses.state")
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 4
|
8
|
-
-
|
9
|
-
version: 0.4.
|
8
|
+
- 1
|
9
|
+
version: 0.4.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Les Hill
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-03-
|
17
|
+
date: 2010-03-17 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -136,6 +136,7 @@ files:
|
|
136
136
|
- examples/simple_object.rb
|
137
137
|
- features/collections.feature
|
138
138
|
- features/finders.feature
|
139
|
+
- features/indexes.feature
|
139
140
|
- features/mongodb.yml
|
140
141
|
- features/mongodoc_base.feature
|
141
142
|
- features/new_record.feature
|
@@ -147,6 +148,7 @@ files:
|
|
147
148
|
- features/step_definitions/document_steps.rb
|
148
149
|
- features/step_definitions/documents.rb
|
149
150
|
- features/step_definitions/finder_steps.rb
|
151
|
+
- features/step_definitions/index_steps.rb
|
150
152
|
- features/step_definitions/json_steps.rb
|
151
153
|
- features/step_definitions/object_steps.rb
|
152
154
|
- features/step_definitions/objects.rb
|
@@ -170,7 +172,6 @@ files:
|
|
170
172
|
- lib/mongo_doc/collection.rb
|
171
173
|
- lib/mongo_doc/connection.rb
|
172
174
|
- lib/mongo_doc/contexts.rb
|
173
|
-
- lib/mongo_doc/contexts/enumerable.rb
|
174
175
|
- lib/mongo_doc/contexts/ids.rb
|
175
176
|
- lib/mongo_doc/contexts/mongo.rb
|
176
177
|
- lib/mongo_doc/criteria.rb
|
@@ -193,11 +194,13 @@ files:
|
|
193
194
|
- lib/mongo_doc/ext/symbol.rb
|
194
195
|
- lib/mongo_doc/ext/time.rb
|
195
196
|
- lib/mongo_doc/finders.rb
|
197
|
+
- lib/mongo_doc/index.rb
|
196
198
|
- lib/mongo_doc/matchers.rb
|
197
199
|
- lib/mongo_doc/query.rb
|
198
200
|
- lib/mongo_doc/scope.rb
|
199
201
|
- lib/mongo_doc/validations/macros.rb
|
200
202
|
- lib/mongo_doc/validations/validates_embedded.rb
|
203
|
+
- lib/mongoid/contexts/enumerable.rb
|
201
204
|
- lib/mongoid/contexts/paging.rb
|
202
205
|
- lib/mongoid/criteria.rb
|
203
206
|
- lib/mongoid/criterion/complex.rb
|
@@ -233,7 +236,6 @@ files:
|
|
233
236
|
- spec/bson_spec.rb
|
234
237
|
- spec/collection_spec.rb
|
235
238
|
- spec/connection_spec.rb
|
236
|
-
- spec/contexts/enumerable_spec.rb
|
237
239
|
- spec/contexts/ids_spec.rb
|
238
240
|
- spec/contexts/mongo_spec.rb
|
239
241
|
- spec/contexts_spec.rb
|
@@ -245,6 +247,7 @@ files:
|
|
245
247
|
- spec/ext_spec.rb
|
246
248
|
- spec/finders_spec.rb
|
247
249
|
- spec/hash_matchers.rb
|
250
|
+
- spec/index_spec.rb
|
248
251
|
- spec/matchers_spec.rb
|
249
252
|
- spec/mongodb.yml
|
250
253
|
- spec/mongodb_pairs.yml
|
@@ -294,7 +297,6 @@ test_files:
|
|
294
297
|
- spec/bson_spec.rb
|
295
298
|
- spec/collection_spec.rb
|
296
299
|
- spec/connection_spec.rb
|
297
|
-
- spec/contexts/enumerable_spec.rb
|
298
300
|
- spec/contexts/ids_spec.rb
|
299
301
|
- spec/contexts/mongo_spec.rb
|
300
302
|
- spec/contexts_spec.rb
|
@@ -306,6 +308,7 @@ test_files:
|
|
306
308
|
- spec/ext_spec.rb
|
307
309
|
- spec/finders_spec.rb
|
308
310
|
- spec/hash_matchers.rb
|
311
|
+
- spec/index_spec.rb
|
309
312
|
- spec/matchers_spec.rb
|
310
313
|
- spec/new_record_spec.rb
|
311
314
|
- spec/query_spec.rb
|
@@ -1,274 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe MongoDoc::Contexts::Enumerable do
|
4
|
-
|
5
|
-
class Address
|
6
|
-
include MongoDoc::Document
|
7
|
-
include MongoDoc::Matchers
|
8
|
-
|
9
|
-
attr_accessor :number
|
10
|
-
attr_accessor :street
|
11
|
-
end
|
12
|
-
|
13
|
-
before do
|
14
|
-
@london = Address.new(:number => 1, :street => "Bond Street")
|
15
|
-
@shanghai = Address.new(:number => 10, :street => "Nan Jing Dong Lu")
|
16
|
-
@melbourne = Address.new(:number => 20, :street => "Bourke Street")
|
17
|
-
@new_york = Address.new(:number => 20, :street => "Broadway")
|
18
|
-
@docs = [ @london, @shanghai, @melbourne, @new_york ]
|
19
|
-
@criteria = Mongoid::Criteria.new(Address)
|
20
|
-
@criteria.documents = @docs
|
21
|
-
@criteria.where(:street => "Bourke Street").only(:number)
|
22
|
-
@context = MongoDoc::Contexts::Enumerable.new(@criteria)
|
23
|
-
end
|
24
|
-
|
25
|
-
describe "#aggregate" do
|
26
|
-
|
27
|
-
before do
|
28
|
-
@counts = @context.aggregate
|
29
|
-
end
|
30
|
-
|
31
|
-
it "groups by the fields provided in the options" do
|
32
|
-
@counts.size.should == 3
|
33
|
-
end
|
34
|
-
|
35
|
-
it "stores the counts in proper groups" do
|
36
|
-
@counts[1].should == 1
|
37
|
-
@counts[10].should == 1
|
38
|
-
@counts[20].should == 2
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
describe "#count" do
|
43
|
-
|
44
|
-
it "returns the size of the enumerable" do
|
45
|
-
@context.count.should == 4
|
46
|
-
end
|
47
|
-
|
48
|
-
end
|
49
|
-
|
50
|
-
describe "#execute" do
|
51
|
-
|
52
|
-
before do
|
53
|
-
@criteria = Mongoid::Criteria.new(Address)
|
54
|
-
@criteria.documents = @docs
|
55
|
-
end
|
56
|
-
|
57
|
-
it "returns the matching documents from the array" do
|
58
|
-
@context.execute.should == [ @melbourne ]
|
59
|
-
end
|
60
|
-
|
61
|
-
context "when selector is empty" do
|
62
|
-
|
63
|
-
before do
|
64
|
-
@criteria.only(:number)
|
65
|
-
@context = MongoDoc::Contexts::Enumerable.new(@criteria)
|
66
|
-
end
|
67
|
-
|
68
|
-
it "returns all the documents" do
|
69
|
-
@context.execute.should == @docs
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
context "when skip and limit are in the options" do
|
74
|
-
|
75
|
-
before do
|
76
|
-
@criteria.skip(2).limit(2)
|
77
|
-
@context = MongoDoc::Contexts::Enumerable.new(@criteria)
|
78
|
-
end
|
79
|
-
|
80
|
-
it "properly narrows down the matching results" do
|
81
|
-
@context.execute.should == [ @melbourne, @new_york ]
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
end
|
86
|
-
|
87
|
-
describe "#first" do
|
88
|
-
|
89
|
-
context "when a selector is present" do
|
90
|
-
|
91
|
-
it "returns the first that matches the selector" do
|
92
|
-
@context.first.should == @melbourne
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
end
|
97
|
-
|
98
|
-
describe "#group" do
|
99
|
-
|
100
|
-
before do
|
101
|
-
@group = @context.group
|
102
|
-
end
|
103
|
-
|
104
|
-
it "groups by the fields provided in the options" do
|
105
|
-
@group.size.should == 3
|
106
|
-
end
|
107
|
-
|
108
|
-
it "stores the documents in proper groups" do
|
109
|
-
@group[1].should == [ @london ]
|
110
|
-
@group[10].should == [ @shanghai ]
|
111
|
-
@group[20].should == [ @melbourne, @new_york ]
|
112
|
-
end
|
113
|
-
|
114
|
-
end
|
115
|
-
|
116
|
-
describe "#initialize" do
|
117
|
-
|
118
|
-
let(:selector) { { :field => "value" } }
|
119
|
-
let(:options) { { :skip => 20 } }
|
120
|
-
let(:documents) { [stub] }
|
121
|
-
|
122
|
-
before do
|
123
|
-
@criteria = Mongoid::Criteria.new(Address)
|
124
|
-
@criteria.documents = documents
|
125
|
-
@criteria.where(selector).skip(20)
|
126
|
-
@context = MongoDoc::Contexts::Enumerable.new(@criteria)
|
127
|
-
end
|
128
|
-
|
129
|
-
it "sets the selector" do
|
130
|
-
@context.selector.should == selector
|
131
|
-
end
|
132
|
-
|
133
|
-
it "sets the options" do
|
134
|
-
@context.options.should == options
|
135
|
-
end
|
136
|
-
|
137
|
-
it "sets the documents" do
|
138
|
-
@context.documents.should == documents
|
139
|
-
end
|
140
|
-
|
141
|
-
end
|
142
|
-
|
143
|
-
describe "#iterator" do
|
144
|
-
|
145
|
-
before do
|
146
|
-
@criteria.where(:street => "Bourke Street")
|
147
|
-
@criteria.documents = @docs
|
148
|
-
@context = MongoDoc::Contexts::Enumerable.new(@criteria)
|
149
|
-
end
|
150
|
-
|
151
|
-
it "executes the criteria" do
|
152
|
-
acc = []
|
153
|
-
@context.iterate do |doc|
|
154
|
-
acc << doc
|
155
|
-
end
|
156
|
-
acc.should == [@melbourne]
|
157
|
-
end
|
158
|
-
|
159
|
-
end
|
160
|
-
|
161
|
-
describe "#last" do
|
162
|
-
|
163
|
-
it "returns the last matching in the enumerable" do
|
164
|
-
@context.last.should == @melbourne
|
165
|
-
end
|
166
|
-
|
167
|
-
end
|
168
|
-
|
169
|
-
describe "#max" do
|
170
|
-
|
171
|
-
it "returns the max value for the supplied field" do
|
172
|
-
@context.max(:number).should == 20
|
173
|
-
end
|
174
|
-
|
175
|
-
end
|
176
|
-
|
177
|
-
describe "#min" do
|
178
|
-
|
179
|
-
it "returns the min value for the supplied field" do
|
180
|
-
@context.min(:number).should == 1
|
181
|
-
end
|
182
|
-
|
183
|
-
end
|
184
|
-
|
185
|
-
describe "#one" do
|
186
|
-
|
187
|
-
it "returns the first matching in the enumerable" do
|
188
|
-
@context.one.should == @melbourne
|
189
|
-
end
|
190
|
-
|
191
|
-
end
|
192
|
-
|
193
|
-
describe "#page" do
|
194
|
-
|
195
|
-
context "when the page option exists" do
|
196
|
-
|
197
|
-
before do
|
198
|
-
@criteria = Mongoid::Criteria.new(Address).extras({ :page => 5 })
|
199
|
-
@criteria.documents = []
|
200
|
-
@context = MongoDoc::Contexts::Enumerable.new(@criteria)
|
201
|
-
end
|
202
|
-
|
203
|
-
it "returns the page option" do
|
204
|
-
@context.page.should == 5
|
205
|
-
end
|
206
|
-
|
207
|
-
end
|
208
|
-
|
209
|
-
context "when the page option does not exist" do
|
210
|
-
|
211
|
-
before do
|
212
|
-
@criteria = Mongoid::Criteria.new(Address)
|
213
|
-
@criteria.documents = []
|
214
|
-
@context = MongoDoc::Contexts::Enumerable.new(@criteria)
|
215
|
-
end
|
216
|
-
|
217
|
-
it "returns 1" do
|
218
|
-
@context.page.should == 1
|
219
|
-
end
|
220
|
-
|
221
|
-
end
|
222
|
-
|
223
|
-
end
|
224
|
-
|
225
|
-
describe "#paginate" do
|
226
|
-
|
227
|
-
before do
|
228
|
-
@criteria = Mongoid::Criteria.new(Address).skip(2).limit(2)
|
229
|
-
@context = MongoDoc::Contexts::Enumerable.new(@criteria)
|
230
|
-
@results = @context.paginate
|
231
|
-
end
|
232
|
-
|
233
|
-
it "executes and paginates the results" do
|
234
|
-
@results.current_page.should == 2
|
235
|
-
@results.per_page.should == 2
|
236
|
-
end
|
237
|
-
|
238
|
-
end
|
239
|
-
|
240
|
-
describe "#per_page" do
|
241
|
-
|
242
|
-
context "when a limit option exists" do
|
243
|
-
|
244
|
-
it "returns 20" do
|
245
|
-
@context.per_page.should == 20
|
246
|
-
end
|
247
|
-
|
248
|
-
end
|
249
|
-
|
250
|
-
context "when a limit option does not exist" do
|
251
|
-
|
252
|
-
before do
|
253
|
-
@criteria = Mongoid::Criteria.new(Address).limit(50)
|
254
|
-
@criteria.documents = []
|
255
|
-
@context = MongoDoc::Contexts::Enumerable.new(@criteria)
|
256
|
-
end
|
257
|
-
|
258
|
-
it "returns the limit" do
|
259
|
-
@context.per_page.should == 50
|
260
|
-
end
|
261
|
-
|
262
|
-
end
|
263
|
-
|
264
|
-
end
|
265
|
-
|
266
|
-
describe "#sum" do
|
267
|
-
|
268
|
-
it "returns the sum of all the field values" do
|
269
|
-
@context.sum(:number).should == 51
|
270
|
-
end
|
271
|
-
|
272
|
-
end
|
273
|
-
|
274
|
-
end
|