mongous 0.2.0 → 0.4.2

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.
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
+