mongous 0.2.0 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +73 -0
  3. data/README.adoc +191 -38
  4. data/README.ja.adoc +192 -39
  5. data/Rakefile +8 -8
  6. data/lib/mongous/base.rb +52 -8
  7. data/lib/mongous/document.rb +36 -13
  8. data/lib/mongous/extention.rb +51 -39
  9. data/lib/mongous/filter.rb +316 -227
  10. data/lib/mongous/version.rb +1 -1
  11. data/mongous.gemspec +4 -4
  12. data/sample/connect_auto_0.rb +9 -0
  13. data/sample/declare_compact_1.rb +6 -8
  14. data/sample/declare_compact_2.rb +38 -0
  15. data/sample/declare_label_1.rb +9 -7
  16. data/sample/declare_ndex_1.rb +8 -6
  17. data/sample/declare_ndex_2.rb +9 -7
  18. data/sample/declare_strict_1.rb +9 -9
  19. data/sample/declare_strict_2.rb +4 -5
  20. data/sample/multi_collection_1.rb +0 -2
  21. data/sample/multi_collection_2.rb +5 -5
  22. data/sample/multi_collection_3.rb +24 -0
  23. data/sample/query_basic_1.rb +8 -2
  24. data/sample/query_basic_2.rb +8 -2
  25. data/sample/query_basic_3.rb +0 -2
  26. data/sample/query_basic_4.rb +3 -5
  27. data/sample/query_basic_5.rb +0 -2
  28. data/sample/query_basic_6.rb +56 -0
  29. data/sample/query_detail_1.rb +3 -3
  30. data/sample/query_detail_2.rb +3 -3
  31. data/sample/query_detail_3.rb +4 -5
  32. data/sample/query_filter_1.rb +1 -3
  33. data/sample/query_filter_2.rb +2 -4
  34. data/sample/query_find_1.rb +6 -5
  35. data/sample/query_select_1.rb +54 -0
  36. data/sample/query_skip_limit_1.rb +25 -14
  37. data/sample/query_skip_limit_2.rb +20 -11
  38. data/sample/query_sort_1.rb +43 -0
  39. data/sample/save_basic_1.rb +2 -6
  40. data/sample/save_basic_2.rb +2 -6
  41. data/sample/save_basic_3.rb +2 -6
  42. data/sample/save_detail_1.rb +3 -3
  43. data/sample/save_detail_2.rb +3 -3
  44. data/sample/save_detail_3.rb +10 -10
  45. data/sample/save_verify_1.rb +6 -6
  46. data/sample/save_verify_2.rb +0 -2
  47. data/sample/save_verify_3.rb +0 -2
  48. data/sample/save_verify_4.rb +0 -2
  49. data/sample/save_verify_5.rb +3 -5
  50. data/sample/save_verify_6.rb +3 -5
  51. data/sample/save_verify_7.rb +21 -0
  52. data/sample/update_basic_1.rb +9 -0
  53. data/sample/zap_basic_1.rb +1 -5
  54. data/sample/zap_basic_2.rb +2 -6
  55. data/sample/zap_basic_3.rb +2 -6
  56. data/sample/zbenchmark_search_1.rb +114 -0
  57. data/sample/zbenchmark_search_2.rb +114 -0
  58. data/sample/zbenchmark_search_3.rb +88 -0
  59. metadata +31 -21
  60. data/sample/query_projection_1.rb +0 -41
  61. data/sample/query_sort_order_1.rb +0 -46
@@ -15,7 +15,7 @@ module Mongous
15
15
  end
16
16
  end
17
17
 
18
- def method_missing( sym, *args, **opts, &block )
18
+ def method_missing( sym, *args, **_opts, &_block )
19
19
  m = /\A(\w+)([=])?\Z/.match( sym.to_s )
20
20
  if args.size == 0 && m[2].nil?
21
21
  self[ m[1] ]
@@ -52,17 +52,25 @@ module Mongous
52
52
  else
53
53
  savemode = :update
54
54
  end
55
+
55
56
  self.class.fields.each do |label, field|
56
- _must = field[:_attrs].include?(:must)
57
+ default_value = getvalue_or_callproc( field[:default] )
58
+ must = field[:_attrs].include?(:must)
57
59
  if @doc.has_key?(label)
58
- if _must && !having?( @doc[label] )
59
- raise Mongous::Error, "must and not having field. : #{ label }"
60
+ if !having?( @doc[label] )
61
+ if default_value
62
+ self[label] = default_value
63
+ elsif must
64
+ raise Mongous::Error, "must but unassigned field. : #{ label }"
65
+ elsif self.class.symbols[:strict]
66
+ self[label] = nil
67
+ end
60
68
  end
61
69
  else
62
- if default_value = getvalue_or_callproc( field[:default] )
70
+ if default_value
63
71
  self[label] = default_value
64
- elsif _must
65
- raise Mongous::Error, "must and unassigned field. : #{ label }"
72
+ elsif must
73
+ raise Mongous::Error, "must but unassigned field. : #{ label }"
66
74
  elsif self.class.symbols[:strict]
67
75
  self[label] = nil
68
76
  end
@@ -70,11 +78,11 @@ module Mongous
70
78
 
71
79
  case savemode
72
80
  when :create
73
- if create_value = getvalue_or_callproc( field[:create] )
81
+ if ( create_value = getvalue_or_callproc( field[:create] ) )
74
82
  self[label] = create_value
75
83
  end
76
84
  when :update
77
- if update_value = getvalue_or_callproc( field[:update] )
85
+ if ( update_value = getvalue_or_callproc( field[:update] ) )
78
86
  self[label] = update_value
79
87
  end
80
88
  end
@@ -92,15 +100,23 @@ module Mongous
92
100
  when :update
93
101
  self.class.collection.update_one( { "_id"=> @doc["_id"] }, { '$set' => @doc } )
94
102
  end
95
-
96
103
  self
97
104
  end
98
105
 
106
+ def to_hash
107
+ @doc.dup
108
+ end
109
+
110
+ def to_json( **opts )
111
+ ::JSON.generate( @doc, **opts )
112
+ end
113
+
99
114
  def []( label )
100
115
  label = label.to_s
101
116
 
102
117
  if self.class.symbols[:strict]
103
- if !self.class.fields.keys.include?(label)
118
+ labels = ["_id"] + self.class.fields.keys
119
+ if !labels.include?( label )
104
120
  raise Mongous::Error, "undefined field. : #{ label }"
105
121
  end
106
122
  end
@@ -128,10 +144,13 @@ module Mongous
128
144
  end
129
145
 
130
146
  field = self.class.fields[label]
131
- return @doc[label] = value if field.nil?
147
+ if field.nil?
148
+ @doc[label] = value
149
+ return
150
+ end
132
151
 
133
152
  types = []
134
- if attrs = field[:_attrs] || []
153
+ if ( attrs = field[:_attrs] || [] )
135
154
  attrs.each do |attr|
136
155
  if attr.class == Class
137
156
  types << attr
@@ -175,6 +194,10 @@ module Mongous
175
194
  if !attr.cover?( value )
176
195
  raise Mongous::Error, "out of range. : #{ label } : #{ value }"
177
196
  end
197
+ when Regexp
198
+ if !attr.match( value )
199
+ raise Mongous::Error, "unmatch regexp. : #{ label } : #{ value }"
200
+ end
178
201
  end
179
202
  end
180
203
  end
@@ -5,87 +5,93 @@ module Mongous
5
5
  if self.class_variable_defined?( :@@client )
6
6
  self.class_variable_get( :@@client )
7
7
  else
8
- _client = Mongous.client
9
- self.class_variable_set( :@@client, _client )
8
+ new_client = Mongous.client
9
+ self.class_variable_set( :@@client, new_client )
10
10
  end
11
11
  end
12
12
 
13
- def client=( _client )
14
- m = /(.*?):(\d+)/.match( caller()[0] )
15
- call_from = [ m[1], m[2] ].join(":")
16
- if !_client.is_a?( Mongo::Client )
17
- raise Mongous::Error, "type invalid. : #{ _client }"
13
+ def client=( new_client )
14
+ if !new_client.is_a?( Mongo::Client )
15
+ m = /(.*?):(\d+)/.match( caller()[0] )
16
+ call_from = [ m[1], m[2] ].join(":")
17
+ raise Mongous::Error, "type invalid. : #{ new_client } at #{ call_from }"
18
18
  end
19
- self.class_variable_set( :@@client, _client )
19
+ self.class_variable_set( :@@client, new_client )
20
20
  end
21
21
 
22
22
  def collection_name
23
23
  if self.class_variable_defined?( :@@collection_name )
24
- self.class_variable_get( :@@collection_name )
25
- else
26
- _client_name = self.name
27
- self.class_variable_set( :@@collection_name, _client_name )
24
+ value = self.class_variable_get( :@@collection_name )
25
+ return value if value
28
26
  end
27
+
28
+ self.class_variable_set( :@@collection_name, self.name )
29
29
  end
30
30
 
31
- def collection_name=( _collection_name )
32
- self.class_variable_set( :@@collection_name, _collection_name )
31
+ def collection_name=( new_collection_name )
32
+ self.class_variable_set( :@@collection_name, new_collection_name )
33
33
  if self.class_variable_defined?( :@@collection )
34
34
  self.remove_class_variable( :@@collection )
35
35
  end
36
36
  end
37
37
 
38
- def collection
39
- if self.class_variable_defined?( :@@collection )
40
- if _collection = self.class_variable_get( :@@collection )
41
- return _collection
38
+ def collection( temp_collection_name = nil )
39
+ if temp_collection_name.nil?
40
+ if self.class_variable_defined?( :@@collection )
41
+ if ( new_collection = self.class_variable_get( :@@collection ) )
42
+ return new_collection
43
+ end
42
44
  end
45
+ new_collection_name = collection_name
46
+ else
47
+ new_collection_name = temp_collection_name
43
48
  end
49
+ new_client = client
44
50
 
45
- _collection_name = collection_name
46
- _client = client
47
-
48
- if _client.database.collection_names.include?( _collection_name )
49
- _collection = _client[ _collection_name ]
51
+ if new_client.database.collection_names.include?( new_collection_name )
52
+ new_collection = new_client[ new_collection_name ]
50
53
  else
51
- _collection = _client[ _collection_name ]
52
- _collection.create
54
+ new_collection = new_client[ new_collection_name ]
55
+ new_collection.create
53
56
  end
54
57
 
55
58
  indexes.each do |keys, opts|
56
- _collection.indexes.create_one( keys, opts ) rescue nil
59
+ new_collection.indexes.create_one( keys, opts ) rescue nil
57
60
  end
58
61
 
59
- self.class_variable_set( :@@collection, _collection )
62
+ self.class_variable_set( :@@collection, new_collection ) if temp_collection_name.nil?
63
+ new_collection
60
64
  end
61
65
 
62
66
  def fields
63
- self_class_variable( :@@fields, {} )
67
+ setup_class_variable( :@@fields, {} )
64
68
  end
65
69
 
66
70
  def symbols
67
- self_class_variable( :@@symbols, {} )
71
+ setup_class_variable( :@@symbols, {} )
68
72
  end
69
73
 
70
74
  def blocks
71
- self_class_variable( :@@blocks, {} )
75
+ setup_class_variable( :@@blocks, {} )
72
76
  end
73
77
 
74
78
  def indexes
75
- self_class_variable( :@@indexes, [] )
79
+ setup_class_variable( :@@indexes, [] )
76
80
  end
77
81
 
78
82
  def filters
79
- self_class_variable( :@@filters, {} )
83
+ setup_class_variable( :@@filters, {} )
80
84
  end
81
85
 
82
86
  def defaults
83
- self_class_variable( :@@defaults, {} )
87
+ setup_class_variable( :@@defaults, {} )
84
88
  end
85
89
 
86
- def self_class_variable( symbol, default )
90
+ def setup_class_variable( symbol, default = {}, &block )
87
91
  if self.class_variable_defined?( symbol )
88
92
  self.class_variable_get( symbol )
93
+ elsif block_given?
94
+ self.class_variable_set( symbol, block.call )
89
95
  else
90
96
  self.class_variable_set( symbol, default )
91
97
  end
@@ -95,6 +101,10 @@ module Mongous
95
101
  self.new( **doc ).save
96
102
  end
97
103
 
104
+ def drop
105
+ self.collection.drop
106
+ end
107
+
98
108
  def find( conditios = {}, options = {} )
99
109
  self.collection.find( conditios, options )
100
110
  end
@@ -104,9 +114,9 @@ module Mongous
104
114
  call_from = [ m[1], m[2] ].join(":")
105
115
 
106
116
  attrs.each do |attr|
107
- if klass = attr.class
108
- if ![Class, Range, Array, Proc, Symbol].include?(klass)
109
- raise Mongous::Error, "field args error. : #{ attr } on #{ symbol } at #{ call_from }"
117
+ if ( klass = attr.class )
118
+ if ![Class, Range, Array, Regexp, Proc, Symbol].include?(klass)
119
+ raise Mongous::Error, "'field' arguments error. : #{ attr } on #{ symbol } at #{ call_from }"
110
120
  end
111
121
  end
112
122
  end
@@ -114,7 +124,7 @@ module Mongous
114
124
  items.each do |key, value|
115
125
  next if [:default, :create, :update].include?(key) && [Proc, String, Numeric].include?(value.class)
116
126
 
117
- raise Mongous::Error, "field opts error. : #{key} on #{ symbol } at #{ call_from }"
127
+ raise Mongous::Error, "'field' options error. : #{key} on #{ symbol } at #{ call_from }"
118
128
  end
119
129
 
120
130
  items[:_attrs] = attrs
@@ -130,6 +140,8 @@ module Mongous
130
140
  m = /(.*?):(\d+)/.match( caller()[0] )
131
141
  call_from = [ m[1], m[2] ].join(":")
132
142
  blocks[call_from] = block
143
+ else
144
+ raise Mongous::Error, "'verify' arguments error. need directives or block."
133
145
  end
134
146
  end
135
147
 
@@ -151,7 +163,7 @@ module Mongous
151
163
  else
152
164
  m = /(.*?):(\d+)/.match( caller()[0] )
153
165
  call_from = [ m[1], m[2] ].join(":")
154
- raise Mongous::Error, "filter error. : #{symbol}, #{filter_or_condition} at #{ call_from }"
166
+ raise Mongous::Error, "'filter' arguments error. : #{symbol}, #{filter_or_condition} at #{ call_from }"
155
167
  end
156
168
  end
157
169
  end
@@ -1,227 +1,316 @@
1
-
2
- module Mongous
3
- module Extention
4
- def count
5
- self.collection.find.count
6
- end
7
-
8
- def first
9
- doc = self.collection.find.first
10
- self.new( **doc ) if doc
11
- end
12
-
13
- def all
14
- self.collection.find.map do |doc|
15
- self.new( **doc )
16
- end
17
- end
18
-
19
- def each( &block )
20
- all.each( &block )
21
- end
22
-
23
- def delete
24
- self.collection.delete_many({})
25
- end
26
-
27
- def where( filter = nil, **conditions )
28
- condition = normalize( filter, conditions )
29
- Filter.new( self ).where( condition )
30
- end
31
-
32
- def not( filter = nil, **conditions )
33
- raise Mongous::Error, "Unset args for #{self}.not." if filter.nil? && conditions.empty?
34
-
35
- condition = normalize( filter, conditions )
36
- Filter.new( self ).where({"$nor" => [condition]})
37
- end
38
-
39
- def and( *filters )
40
- raise Mongous::Error, "Unset args for #{self}.and." if filters.empty?
41
-
42
- conditions = filters.map do |filter|
43
- normalize( filter, {} )
44
- end
45
- Filter.new( self ).where({"$and" => conditions})
46
- end
47
-
48
- def or( *filters )
49
- raise Mongous::Error, "Unset args for #{self}.or." if filters.empty?
50
-
51
- conditions = filters.map do |filter|
52
- normalize( filter, {} )
53
- end
54
- Filter.new( self ).where({"$or" => conditions})
55
- end
56
-
57
- def normalize( filter, conditions )
58
- condition = case filter
59
- when Filter
60
- filter.to_condition
61
- when Symbol
62
- case _filter = filters[filter]
63
- when Filter
64
- _filter.to_condition
65
- when Hash
66
- _filter
67
- end
68
- when NilClass
69
- Filter.new( self ).where( **conditions ).to_condition
70
- else
71
- caller_method = /`(.*?)'/.match( caller()[0] )[1]
72
- raise Mongous::Error, "Invalid args for #{self}.#{ caller_method }. : #{filter}, #{conditions}"
73
- end
74
- end
75
- end
76
- end
77
-
78
- module Mongous
79
- class Filter
80
- def initialize( klass )
81
- @klass = klass
82
- @filter = {}
83
- @option = {}
84
- end
85
-
86
- def where( conditions )
87
- hash = {}
88
- conditions.each do |key, item|
89
- case key
90
- when /\$(and|or|nor)/
91
- hash[key] = item
92
-
93
- else
94
- case item
95
- when Array
96
- hash[key] = {"$in"=>item}
97
-
98
- when Range
99
- _begin_oper = "$gte"
100
- _end_oper = item.exclude_end? ? "$lt" : "$lte"
101
-
102
- if item.begin && item.end
103
- hash[key] = { _begin_oper => item.begin, _end_oper => item.end }
104
-
105
- elsif !item.begin && item.end
106
- hash[key] = { _end_oper => item.end }
107
-
108
- elsif item.begin && !item.end
109
- hash[key] = { _begin_oper => item.begin }
110
-
111
- else
112
- raise Mongous::Error, "invalid range. : #{ item }"
113
-
114
- end
115
-
116
- else
117
- hash[key] = item
118
-
119
- end
120
- end
121
- end
122
- @filter.merge!( hash )
123
- self.dup
124
- end
125
-
126
- def to_condition
127
- @filter.dup
128
- end
129
-
130
- def option( _option )
131
- @option.merge!( _option )
132
- self.dup
133
- end
134
-
135
- def projection( _projection )
136
- @projection = _projection
137
- self.dup
138
- end
139
- alias :select :projection
140
-
141
- def sort( _sort )
142
- @sort = _sort
143
- self.dup
144
- end
145
- alias :order :sort
146
-
147
- def []( nth_or_range, len = nil )
148
- case nth_or_range
149
- when Integer
150
- @skip = nth_or_range
151
-
152
- if len
153
- raise Mongous::Error, "invalid len. : #{ len }" if !len.is_a? Integer || len <= 0
154
- @limit = len
155
- end
156
-
157
- when Range
158
- from = nth_or_range.begin
159
- raise Mongous::Error, "invalid range. : #{ nth_or_range }" unless from.is_a? Integer
160
-
161
- to = nth_or_range.end
162
- raise Mongous::Error, "invalid range. : #{ nth_or_range }" unless to.is_a? Integer
163
-
164
- to -= 1 if nth_or_range.exclude_end?
165
- @skip = from
166
- @limit = to - from + 1
167
-
168
- else
169
- raise Mongous::Error, "invalid class. : #{ nth_or_range }"
170
-
171
- end
172
-
173
- self.dup
174
- end
175
-
176
- def do_find
177
- _filter = @filter
178
- _option = @option
179
- _option[:projection] = @projection if @projection
180
- found = @klass.collection.find( _filter, _option )
181
- found = found.sort( @sort ) if @sort
182
- found = found.skip( @skip ) if @skip
183
- found = found.limit( @limit ) if @limit
184
- found
185
- end
186
-
187
- def count
188
- _count = do_find.count
189
- if @skip
190
- if @skip > _count
191
- 0
192
- elsif @limit
193
- [_count - @skip, @limit].min
194
- else
195
- _count - @skip
196
- end
197
- else
198
- if @limit
199
- [_count, @limit].min
200
- else
201
- _count
202
- end
203
- end
204
- end
205
-
206
- def first
207
- doc = do_find.first
208
- @klass.new( **doc ) if doc
209
- end
210
-
211
- def all
212
- do_find.map do |doc|
213
- @klass.new( **doc )
214
- end
215
- end
216
-
217
- def each( &block )
218
- all.each( &block )
219
- end
220
-
221
- def delete
222
- _filter = @filter
223
- @klass.collection.delete_many( _filter )
224
- end
225
- end
226
- end
227
-
1
+
2
+ module Mongous
3
+ module Extention
4
+ def count
5
+ self.collection.estimated_document_count
6
+ end
7
+
8
+ def all
9
+ self.collection.find.map do |doc|
10
+ self.new( **doc )
11
+ end
12
+ end
13
+
14
+ def each( &block )
15
+ all.each( &block )
16
+ end
17
+
18
+ def map( &block )
19
+ all.map( &block )
20
+ end
21
+
22
+ def delete
23
+ self.collection.delete_many({})
24
+ end
25
+
26
+ def attach( collection_name )
27
+ Filter.new( self ).attach( collection_name )
28
+ end
29
+
30
+ def []( nth_or_range, len = nil )
31
+ Filter.new( self )[ nth_or_range, len ]
32
+ end
33
+
34
+ def first
35
+ Filter.new( self ).first
36
+ end
37
+
38
+ def last
39
+ Filter.new( self ).last
40
+ end
41
+
42
+ def sort( *keys, **hash )
43
+ Filter.new( self ).sort( *keys, **hash )
44
+ end
45
+
46
+ def select( *keys, **hash )
47
+ Filter.new( self ).select( *keys, **hash )
48
+ end
49
+
50
+ def where( filter = nil, **conditions )
51
+ condition = normalize( filter, conditions )
52
+ Filter.new( self ).where( condition )
53
+ end
54
+
55
+ def not( filter = nil, **conditions )
56
+ raise Mongous::Error, "Unset args for #{self}.not." if filter.nil? && conditions.empty?
57
+
58
+ condition = normalize( filter, conditions )
59
+ Filter.new( self ).not( condition )
60
+ end
61
+
62
+ def and( *filters )
63
+ raise Mongous::Error, "Unset args for #{self}.and." if filters.empty?
64
+
65
+ conditions = filters.map do |filter|
66
+ normalize( filter, {} )
67
+ end
68
+ Filter.new( self ).where({"$and" => conditions})
69
+ end
70
+
71
+ def or( *filters )
72
+ raise Mongous::Error, "Unset args for #{self}.or." if filters.empty?
73
+
74
+ conditions = filters.map do |filter|
75
+ normalize( filter, {} )
76
+ end
77
+ Filter.new( self ).where({"$or" => conditions})
78
+ end
79
+
80
+ def normalize( filter, conditions )
81
+ case filter
82
+ when Filter
83
+ filter.to_condition
84
+ when Symbol
85
+ case ( new_filter = filters[filter] )
86
+ when Filter
87
+ new_filter.to_condition
88
+ when Hash
89
+ new_filter
90
+ end
91
+ when NilClass
92
+ Filter.new( self ).where( conditions ).to_condition
93
+ else
94
+ caller_method = /`(.*?)'/.match( caller()[0] )[1]
95
+ raise Mongous::Error, "Invalid args for #{self}.#{ caller_method }. : #{filter}, #{conditions}"
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ module Mongous
102
+ class Filter
103
+ def initialize( klass )
104
+ @klass = klass
105
+ @filter = {}
106
+ @option = {}
107
+ end
108
+
109
+ def attach( collection_name )
110
+ w = self.dup
111
+ w.instance_variable_set( :@collection_name, collection_name.to_s )
112
+ w
113
+ end
114
+
115
+ def build_condition( conditions )
116
+ hash = {}
117
+ conditions.each do |key, item|
118
+ case key
119
+ when /\$(and|or|nor)/
120
+ hash[key] = item
121
+
122
+ else
123
+ case item
124
+ when Array
125
+ hash[key] = {"$in"=>item}
126
+
127
+ when Range
128
+ begin_oper = "$gte"
129
+ end_oper = item.exclude_end? ? "$lt" : "$lte"
130
+
131
+ if item.begin && item.end
132
+ hash[key] = { begin_oper => item.begin, end_oper => item.end }
133
+
134
+ elsif !item.begin && item.end
135
+ hash[key] = { end_oper => item.end }
136
+
137
+ elsif item.begin && !item.end
138
+ hash[key] = { begin_oper => item.begin }
139
+
140
+ else
141
+ raise Mongous::Error, "invalid range. : #{ item }"
142
+
143
+ end
144
+
145
+ else
146
+ hash[key] = item
147
+
148
+ end
149
+ end
150
+ end
151
+ hash
152
+ end
153
+
154
+ def where( conditions = {} )
155
+ hash = build_condition( conditions )
156
+ w = self.dup
157
+ w.instance_variable_set( :@filter, @filter.merge( hash ) )
158
+ w
159
+ end
160
+
161
+ def not( conditions = {} )
162
+ hash = build_condition( conditions )
163
+ w = self.dup
164
+ w.instance_variable_set( :@filter, @filter.merge( {"$nor" => [hash]} ) )
165
+ w
166
+ end
167
+
168
+ def to_condition
169
+ @filter.dup
170
+ end
171
+
172
+ def option( new_option )
173
+ w = self.dup
174
+ w.instance_variable_set( :@option, @option.merge( new_option ) )
175
+ w
176
+ end
177
+
178
+ def select( *keys, **hash )
179
+ if not keys.empty?
180
+ new_projection = Hash[ keys.zip( Array.new(keys.length, 1) ) ]
181
+ elsif not hash.empty?
182
+ new_projection = hash
183
+ else
184
+ new_projection = nil
185
+ end
186
+ w = self.dup
187
+ w.instance_variable_set( :@projection, new_projection )
188
+ w
189
+ end
190
+
191
+ def sort( *keys, **hash )
192
+ if not keys.empty?
193
+ new_sort = Hash[ keys.zip( Array.new( keys.length, 1 ) ) ]
194
+ elsif not hash.empty?
195
+ new_sort = hash
196
+ else
197
+ new_sort = nil
198
+ end
199
+ w = self.dup
200
+ w.instance_variable_set( :@sort, new_sort )
201
+ w
202
+ end
203
+
204
+ def []( nth_or_range, len = nil )
205
+ case nth_or_range
206
+ when Integer
207
+ new_skip = nth_or_range
208
+
209
+ if len.is_a?(NilClass)
210
+ new_limit = 1
211
+ elsif len.is_a?(Integer) && len == 0
212
+ new_limit = nil
213
+ elsif len.is_a?(Integer) && len > 0
214
+ new_limit = len
215
+ else
216
+ raise Mongous::Error, "invalid len. : #{ len }"
217
+ end
218
+
219
+ when Range
220
+ from = nth_or_range.begin
221
+ raise Mongous::Error, "invalid range. : #{ nth_or_range }" unless from.is_a? Integer
222
+
223
+ to = nth_or_range.end
224
+ raise Mongous::Error, "invalid range. : #{ nth_or_range }" unless to.is_a? Integer
225
+
226
+ to -= 1 if nth_or_range.exclude_end?
227
+ new_skip = from
228
+ new_limit = to - from + 1
229
+
230
+ else
231
+ raise Mongous::Error, "invalid class. : #{ nth_or_range }"
232
+
233
+ end
234
+
235
+ w = self.dup
236
+ w.instance_variable_set( :@skip, new_skip )
237
+ w.instance_variable_set( :@limit, new_limit )
238
+ w
239
+ end
240
+
241
+ def exec_query
242
+ new_filter = @filter
243
+ new_option = @option.dup
244
+ new_option[:projection] = @projection if @projection
245
+ found = @klass.collection( @collection_name ).find( new_filter, new_option )
246
+ found = found.sort( @sort ) if @sort
247
+ found = found.skip( @skip ) if @skip
248
+ found = found.limit( @limit ) if @limit
249
+ found
250
+ end
251
+
252
+ def count
253
+ found = @klass.collection.find( @filter )
254
+ found = found.skip( @skip ) if @skip
255
+ found = found.limit( @limit ) if @limit
256
+ new_count = found.count_documents
257
+ if @skip
258
+ if @skip > new_count
259
+ 0
260
+ elsif @limit
261
+ [new_count - @skip, @limit].min
262
+ else
263
+ new_count - @skip
264
+ end
265
+ else
266
+ if @limit
267
+ [new_count, @limit].min
268
+ else
269
+ new_count
270
+ end
271
+ end
272
+ end
273
+
274
+ def first
275
+ new_filter = @filter
276
+ new_option = @option.dup
277
+ new_option[:projection] = @projection if @projection
278
+ found = @klass.collection( @collection_name ).find( new_filter, new_option )
279
+ new_order = @sort || { _id: 1 }
280
+ doc = found.sort( new_order ).first
281
+ @klass.new( **doc ) if doc
282
+ end
283
+
284
+ def last
285
+ new_filter = @filter
286
+ new_option = @option.dup
287
+ new_option[:projection] = @projection if @projection
288
+ found = @klass.collection( @collection_name ).find( new_filter, new_option )
289
+ new_order = {}
290
+ ( @sort || {_id: 1} ).each do |k,v|
291
+ new_order[k] = - v
292
+ end
293
+ doc = found.sort( new_order ).first
294
+ @klass.new( **doc ) if doc
295
+ end
296
+
297
+ def all
298
+ exec_query.map do |doc|
299
+ @klass.new( **doc )
300
+ end
301
+ end
302
+
303
+ def each( &block )
304
+ all.each( &block )
305
+ end
306
+
307
+ def map( &block )
308
+ all.map( &block )
309
+ end
310
+
311
+ def delete
312
+ @klass.collection.delete_many( @filter )
313
+ end
314
+ end
315
+ end
316
+