mongous 0.1.4 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +156 -37
  3. data/README.ja.adoc +155 -36
  4. data/lib/mongous/document.rb +66 -31
  5. data/lib/mongous/extention.rb +59 -46
  6. data/lib/mongous/filter.rb +82 -60
  7. data/lib/mongous/version.rb +1 -1
  8. data/sample/connect_auto_2.rb +2 -1
  9. data/sample/connect_default_2.rb +2 -1
  10. data/sample/connect_environ_2.rb +2 -1
  11. data/sample/connect_loadfile_2.rb +2 -1
  12. data/sample/declare_compact_1.rb +4 -3
  13. data/sample/declare_label_1.rb +5 -3
  14. data/sample/declare_ndex_1.rb +5 -3
  15. data/sample/declare_ndex_2.rb +5 -3
  16. data/sample/declare_strict_1.rb +14 -10
  17. data/sample/declare_strict_2.rb +5 -3
  18. data/sample/{multi_docs_1.rb → multi_collection_1.rb} +0 -0
  19. data/sample/multi_collection_2.rb +63 -0
  20. data/sample/query_basic_1.rb +3 -1
  21. data/sample/query_basic_2.rb +5 -3
  22. data/sample/query_basic_3.rb +2 -3
  23. data/sample/query_basic_4.rb +3 -4
  24. data/sample/query_basic_5.rb +2 -3
  25. data/sample/query_detail_1.rb +1 -0
  26. data/sample/query_detail_2.rb +1 -0
  27. data/sample/query_detail_3.rb +5 -3
  28. data/sample/{query_basic_6.rb → query_filter_1.rb} +8 -5
  29. data/sample/query_filter_2.rb +50 -0
  30. data/sample/query_find_1.rb +31 -0
  31. data/sample/query_projection_1.rb +5 -8
  32. data/sample/query_skip_limit_1.rb +47 -0
  33. data/sample/query_skip_limit_2.rb +49 -0
  34. data/sample/query_sort_order_1.rb +46 -0
  35. data/sample/save_basic_1.rb +1 -2
  36. data/sample/save_basic_2.rb +1 -2
  37. data/sample/save_basic_3.rb +1 -2
  38. data/sample/save_detail_1.rb +7 -4
  39. data/sample/save_detail_2.rb +7 -4
  40. data/sample/save_detail_3.rb +10 -7
  41. data/sample/save_verify_1.rb +7 -4
  42. data/sample/save_verify_3.rb +1 -1
  43. data/sample/save_verify_5.rb +3 -3
  44. data/sample/save_verify_6.rb +3 -3
  45. data/sample/save_verify_7.rb +23 -0
  46. data/sample/update_basic_1.rb +13 -0
  47. data/sample/zap_basic_2.rb +2 -2
  48. metadata +12 -11
  49. data/sample/multi_docs_2.rb +0 -58
  50. data/sample/query_limit_1.rb +0 -44
  51. data/sample/query_order_1.rb +0 -49
  52. data/sample/query_raw_1.rb +0 -33
  53. data/sample/template_article.rb +0 -5
  54. data/sample/template_person.rb +0 -12
  55. data/sample/zap_basic_3.rb +0 -11
@@ -26,33 +26,66 @@ module Mongous
26
26
  end
27
27
  end
28
28
 
29
- def having?( value )
30
- case value
29
+ def having?( label )
30
+ case label
31
31
  when NilClass
32
32
  false
33
33
  when String
34
- !value.strip.empty?
34
+ !label.strip.empty?
35
35
  else
36
36
  true
37
37
  end
38
38
  end
39
39
 
40
+ def getvalue_or_callproc( value_or_proc )
41
+ case value_or_proc
42
+ when Proc
43
+ value_or_proc.call
44
+ else
45
+ value_or_proc
46
+ end
47
+ end
48
+
40
49
  def save
50
+ if @doc["_id"].nil? || self.class.collection.find( { "_id"=> @doc["_id"] } ).count == 0
51
+ savemode = :create
52
+ else
53
+ savemode = :update
54
+ end
55
+
41
56
  self.class.fields.each do |label, field|
42
- _must = field[:_args].include?(:must)
57
+ default_value = getvalue_or_callproc( field[:default] )
58
+ _must = field[:_attrs].include?(:must)
43
59
  if @doc.has_key?(label)
44
- if _must && !having?( @doc[label] )
45
- 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
46
68
  end
47
69
  else
48
- if block = field[:_block]
49
- self[label] = block.call
70
+ if default_value
71
+ self[label] = default_value
50
72
  elsif _must
51
- raise Mongous::Error, "must and unassigned field. : #{ label }"
73
+ raise Mongous::Error, "must but unassigned field. : #{ label }"
52
74
  elsif self.class.symbols[:strict]
53
75
  self[label] = nil
54
76
  end
55
77
  end
78
+
79
+ case savemode
80
+ when :create
81
+ if create_value = getvalue_or_callproc( field[:create] )
82
+ self[label] = create_value
83
+ end
84
+ when :update
85
+ if update_value = getvalue_or_callproc( field[:update] )
86
+ self[label] = update_value
87
+ end
88
+ end
56
89
  end
57
90
 
58
91
  self.class.blocks.each do |call_from, block|
@@ -61,15 +94,13 @@ module Mongous
61
94
  end
62
95
  end
63
96
 
64
- if @doc["_id"]
65
- _filter = { "_id"=> @doc["_id"] }
66
- if self.class.collection.find( _filter ).first
67
- self.class.collection.update_one( _filter, { '$set' => @doc } )
68
- return self
69
- end
97
+ case savemode
98
+ when :create
99
+ self.class.collection.insert_one( @doc )
100
+ when :update
101
+ self.class.collection.update_one( { "_id"=> @doc["_id"] }, { '$set' => @doc } )
70
102
  end
71
103
 
72
- self.class.collection.insert_one( @doc )
73
104
  self
74
105
  end
75
106
 
@@ -77,7 +108,7 @@ module Mongous
77
108
  label = label.to_s
78
109
 
79
110
  if self.class.symbols[:strict]
80
- if !self.class.fields.keys.include?(label)
111
+ if !(self.class.fields.keys.include?(label) || (label == "_id"))
81
112
  raise Mongous::Error, "undefined field. : #{ label }"
82
113
  end
83
114
  end
@@ -108,18 +139,18 @@ module Mongous
108
139
  return @doc[label] = value if field.nil?
109
140
 
110
141
  types = []
111
- if args = field[:_args] || []
112
- args.each do |arg|
113
- if arg.class == Class
114
- types << arg
115
- args -= [arg]
142
+ if attrs = field[:_attrs] || []
143
+ attrs.each do |attr|
144
+ if attr.class == Class
145
+ types << attr
146
+ attrs -= [attr]
116
147
  break
117
148
  end
118
149
  end
119
150
  end
120
151
 
121
152
  if !types.empty?
122
- if !(args & [:must, :not_null]).empty?
153
+ if !(attrs & [:must, :not_null]).empty?
123
154
  if !types.include?( value.class )
124
155
  raise Mongous::Error, "invalid type. : #{ label } : #{ value.class }"
125
156
  end
@@ -129,7 +160,7 @@ module Mongous
129
160
  end
130
161
  end
131
162
  else
132
- if !(args & [:must, :not_null]).empty?
163
+ if !(attrs & [:must, :not_null]).empty?
133
164
  if [NilClass].include?( value.class )
134
165
  raise Mongous::Error, "invalid type. : #{ label } : #{ value.class }"
135
166
  end
@@ -138,19 +169,23 @@ module Mongous
138
169
 
139
170
  @doc[label] = value
140
171
 
141
- args.each do |arg|
142
- case arg
172
+ attrs.each do |attr|
173
+ case attr
143
174
  when Proc
144
- if !self.instance_eval( &arg )
175
+ if !self.instance_eval( &attr )
145
176
  raise Mongous::Error, "violation detected. : #{ label } : #{ value }"
146
177
  end
147
178
  when Array
148
- if !arg.include?( value )
149
- raise Mongous::Error, "not include. : #{ label } :#{ value }"
179
+ if !attr.include?( value )
180
+ raise Mongous::Error, "not include. : #{ label } : #{ value }"
150
181
  end
151
182
  when Range
152
- if !arg.cover?( value )
153
- raise Mongous::Error, "out of range. : #{ label } :#{ value }"
183
+ if !attr.cover?( value )
184
+ raise Mongous::Error, "out of range. : #{ label } : #{ value }"
185
+ end
186
+ when Regexp
187
+ if !attr.match( value )
188
+ raise Mongous::Error, "unmatch regexp. : #{ label } : #{ value }"
154
189
  end
155
190
  end
156
191
  end
@@ -10,7 +10,7 @@ module Mongous
10
10
  end
11
11
  end
12
12
 
13
- def set_client( _client )
13
+ def client=( _client )
14
14
  m = /(.*?):(\d+)/.match( caller()[0] )
15
15
  call_from = [ m[1], m[2] ].join(":")
16
16
  if !_client.is_a?( Mongo::Client )
@@ -28,7 +28,7 @@ module Mongous
28
28
  end
29
29
  end
30
30
 
31
- def set_collection_name( _collection_name )
31
+ def collection_name=( _collection_name )
32
32
  self.class_variable_set( :@@collection_name, _collection_name )
33
33
  if self.class_variable_defined?( :@@collection )
34
34
  self.remove_class_variable( :@@collection )
@@ -60,34 +60,34 @@ module Mongous
60
60
  end
61
61
 
62
62
  def fields
63
- if self.class_variable_defined?( :@@fields )
64
- self.class_variable_get( :@@fields )
65
- else
66
- self.class_variable_set( :@@fields, {} )
67
- end
63
+ self_class_variable( :@@fields, {} )
68
64
  end
69
65
 
70
66
  def symbols
71
- if self.class_variable_defined?( :@@symbols )
72
- self.class_variable_get( :@@symbols )
73
- else
74
- self.class_variable_set( :@@symbols, {} )
75
- end
67
+ self_class_variable( :@@symbols, {} )
76
68
  end
77
69
 
78
70
  def blocks
79
- if self.class_variable_defined?( :@@blocks )
80
- self.class_variable_get( :@@blocks )
81
- else
82
- self.class_variable_set( :@@blocks, {} )
83
- end
71
+ self_class_variable( :@@blocks, {} )
84
72
  end
85
73
 
86
74
  def indexes
87
- if self.class_variable_defined?( :@@indexes )
88
- self.class_variable_get( :@@indexes )
75
+ self_class_variable( :@@indexes, [] )
76
+ end
77
+
78
+ def filters
79
+ self_class_variable( :@@filters, {} )
80
+ end
81
+
82
+ def defaults
83
+ self_class_variable( :@@defaults, {} )
84
+ end
85
+
86
+ def self_class_variable( symbol, default )
87
+ if self.class_variable_defined?( symbol )
88
+ self.class_variable_get( symbol )
89
89
  else
90
- self.class_variable_set( :@@indexes, [] )
90
+ self.class_variable_set( symbol, default )
91
91
  end
92
92
  end
93
93
 
@@ -95,53 +95,66 @@ module Mongous
95
95
  self.new( **doc ).save
96
96
  end
97
97
 
98
- def field( label, *args, **opts, &block )
98
+ def find( conditios = {}, options = {} )
99
+ self.collection.find( conditios, options )
100
+ end
101
+
102
+ def field( symbol, *attrs, **items )
99
103
  m = /(.*?):(\d+)/.match( caller()[0] )
100
104
  call_from = [ m[1], m[2] ].join(":")
101
105
 
102
- args.each do |arg|
103
- if klass = arg.class
104
- if ![Class, Range, Array, Proc, Symbol].include?(klass)
105
- raise Mongous::Error, "field error. : #{arg} on #{ label } at #{ call_from }"
106
+ attrs.each do |attr|
107
+ if klass = attr.class
108
+ if ![Class, Range, Array, Regexp, Proc, Symbol].include?(klass)
109
+ raise Mongous::Error, "'field' arguments error. : #{ attr } on #{ symbol } at #{ call_from }"
106
110
  end
107
111
  end
108
112
  end
109
113
 
110
- opts.each do |key, value|
111
- case key
112
- when :default
113
- case value
114
- when Proc, String, Numeric
115
- else
116
- raise Mongous::Error, "field error. : #{key} on #{ label } at #{ call_from }"
117
- end
118
- end
114
+ items.each do |key, value|
115
+ next if [:default, :create, :update].include?(key) && [Proc, String, Numeric].include?(value.class)
116
+
117
+ raise Mongous::Error, "'field' options error. : #{key} on #{ symbol } at #{ call_from }"
119
118
  end
120
119
 
121
- opts[:_args] = args
122
- opts[:_block] = block
123
- fields[label.to_s] = opts
120
+ items[:_attrs] = attrs
121
+ fields[symbol.to_s] = items
124
122
  end
125
123
 
126
- def verify( *syms, &block )
127
- if !syms.empty?
128
- syms.each do |sym|
129
- symbols[sym] = true
124
+ def verify( *directives, &block )
125
+ if !directives.empty?
126
+ directives.each do |directive|
127
+ symbols[directive] = true
130
128
  end
131
129
  elsif block
132
130
  m = /(.*?):(\d+)/.match( caller()[0] )
133
131
  call_from = [ m[1], m[2] ].join(":")
134
132
  blocks[call_from] = block
133
+ else
134
+ raise Mongous::Error, "'verify' arguments error. need directives or block."
135
135
  end
136
136
  end
137
137
 
138
- def index( *syms, **opts )
139
- opts[:background] = true unless opts.has_key?(:background)
138
+ def index( *symbols, **options )
139
+ options[:background] = true unless options.has_key?(:background)
140
140
  keys = {}
141
- syms.each do |sym|
142
- keys[sym] = 1
141
+ symbols.each do |symbol|
142
+ keys[symbol] = 1
143
+ end
144
+ indexes.push << [keys, options]
145
+ end
146
+
147
+ def filter( symbol, filter_or_condition )
148
+ case filter_or_condition
149
+ when Filter
150
+ filters[symbol] = filter_or_condition.to_condition
151
+ when Hash
152
+ filters[symbol] = filter_or_condition
153
+ else
154
+ m = /(.*?):(\d+)/.match( caller()[0] )
155
+ call_from = [ m[1], m[2] ].join(":")
156
+ raise Mongous::Error, "'filter' arguments error. : #{symbol}, #{filter_or_condition} at #{ call_from }"
143
157
  end
144
- indexes.push << [keys, opts]
145
158
  end
146
159
  end
147
160
  end
@@ -1,6 +1,11 @@
1
1
 
2
2
  module Mongous
3
3
  module Extention
4
+ def count
5
+ # self.collection.find.count
6
+ self.collection.estimated_document_count
7
+ end
8
+
4
9
  def first
5
10
  doc = self.collection.find.first
6
11
  self.new( **doc ) if doc
@@ -20,55 +25,53 @@ module Mongous
20
25
  self.collection.delete_many({})
21
26
  end
22
27
 
23
- def filter( **conditions )
24
- Filter.new( self ).filter( conditions )
28
+ def where( filter = nil, **conditions )
29
+ condition = normalize( filter, conditions )
30
+ Filter.new( self ).where( condition )
25
31
  end
26
32
 
27
33
  def not( filter = nil, **conditions )
28
34
  raise Mongous::Error, "Unset args for #{self}.not." if filter.nil? && conditions.empty?
29
35
 
30
- filter ||= conditions
31
- condition = case filter
32
- when Hash
33
- filter
34
- when Filter
35
- filter.to_condition
36
- else
37
- raise Mongous::Error, "Invalid args for #{self}.not. : #{filter}"
38
- end
39
- Filter.new( self ).filter({"$nor" => [condition]})
36
+ condition = normalize( filter, conditions )
37
+ Filter.new( self ).where({"$nor" => [condition]})
40
38
  end
41
39
 
42
40
  def and( *filters )
43
41
  raise Mongous::Error, "Unset args for #{self}.and." if filters.empty?
44
42
 
45
43
  conditions = filters.map do |filter|
46
- case filter
47
- when Hash
48
- filter
49
- when Filter
50
- filter.to_condition
51
- else
52
- raise Mongous::Error, "Invalid args for #{self}.and. : #{filter}"
53
- end
44
+ normalize( filter, {} )
54
45
  end
55
- Filter.new( self ).filter({"$and" => conditions})
46
+ Filter.new( self ).where({"$and" => conditions})
56
47
  end
57
48
 
58
49
  def or( *filters )
59
50
  raise Mongous::Error, "Unset args for #{self}.or." if filters.empty?
60
51
 
61
52
  conditions = filters.map do |filter|
62
- case filter
63
- when Hash
64
- filter
53
+ normalize( filter, {} )
54
+ end
55
+ Filter.new( self ).where({"$or" => conditions})
56
+ end
57
+
58
+ def normalize( filter, conditions )
59
+ condition = case filter
60
+ when Filter
61
+ filter.to_condition
62
+ when Symbol
63
+ case _filter = filters[filter]
65
64
  when Filter
66
- filter.to_condition
67
- else
68
- raise Mongous::Error, "Invalid args for #{self}.or. : #{filter}"
65
+ _filter.to_condition
66
+ when Hash
67
+ _filter
69
68
  end
69
+ when NilClass
70
+ Filter.new( self ).where( **conditions ).to_condition
71
+ else
72
+ caller_method = /`(.*?)'/.match( caller()[0] )[1]
73
+ raise Mongous::Error, "Invalid args for #{self}.#{ caller_method }. : #{filter}, #{conditions}"
70
74
  end
71
- Filter.new( self ).filter({"$or" => conditions})
72
75
  end
73
76
  end
74
77
  end
@@ -81,7 +84,7 @@ module Mongous
81
84
  @option = {}
82
85
  end
83
86
 
84
- def filter( conditions )
87
+ def where( conditions )
85
88
  hash = {}
86
89
  conditions.each do |key, item|
87
90
  case key
@@ -126,56 +129,54 @@ module Mongous
126
129
  end
127
130
 
128
131
  def option( _option )
129
- self.option!( _option )
130
- self.dup
131
- end
132
-
133
- def option!( _option )
134
132
  @option.merge!( _option )
133
+ self.dup
135
134
  end
136
135
 
137
136
  def projection( _projection )
138
- self.projection!( _projection )
137
+ @projection = _projection
139
138
  self.dup
140
139
  end
141
140
  alias :select :projection
142
141
 
143
- def projection!( _projection )
144
- @projection = _projection
145
- end
146
-
147
142
  def sort( _sort )
148
- self.sort!( _sort )
143
+ @sort = _sort
149
144
  self.dup
150
145
  end
151
146
  alias :order :sort
152
147
 
153
- def sort!( _sort )
154
- @sort = _sort
155
- end
148
+ def []( nth_or_range, len = nil )
149
+ case nth_or_range
150
+ when Integer
151
+ @skip = nth_or_range
156
152
 
157
- def skip( _skip )
158
- self.skip!( _skip )
159
- self.dup
160
- end
161
- alias :offset :skip
153
+ if len
154
+ raise Mongous::Error, "invalid len. : #{ len }" if !len.is_a? Integer || len <= 0
155
+ @limit = len
156
+ end
162
157
 
163
- def skip!( _skip )
164
- @skip = _skip
165
- end
158
+ when Range
159
+ from = nth_or_range.begin
160
+ raise Mongous::Error, "invalid range. : #{ nth_or_range }" unless from.is_a? Integer
166
161
 
167
- def limit( _limit )
168
- self.limit!( _limit )
169
- self.dup
170
- end
162
+ to = nth_or_range.end
163
+ raise Mongous::Error, "invalid range. : #{ nth_or_range }" unless to.is_a? Integer
164
+
165
+ to -= 1 if nth_or_range.exclude_end?
166
+ @skip = from
167
+ @limit = to - from + 1
168
+
169
+ else
170
+ raise Mongous::Error, "invalid class. : #{ nth_or_range }"
171
+
172
+ end
171
173
 
172
- def limit!( _limit )
173
- @limit = _limit
174
+ self.dup
174
175
  end
175
176
 
176
177
  def do_find
177
178
  _filter = @filter
178
- _option = @option
179
+ _option = @option.dup
179
180
  _option[:projection] = @projection if @projection
180
181
  found = @klass.collection.find( _filter, _option )
181
182
  found = found.sort( @sort ) if @sort
@@ -184,6 +185,28 @@ module Mongous
184
185
  found
185
186
  end
186
187
 
188
+ def count
189
+ found = @klass.collection.find( @filter )
190
+ found = found.skip( @skip ) if @skip
191
+ found = found.limit( @limit ) if @limit
192
+ _count = found.count_documents
193
+ if @skip
194
+ if @skip > _count
195
+ 0
196
+ elsif @limit
197
+ [_count - @skip, @limit].min
198
+ else
199
+ _count - @skip
200
+ end
201
+ else
202
+ if @limit
203
+ [_count, @limit].min
204
+ else
205
+ _count
206
+ end
207
+ end
208
+ end
209
+
187
210
  def first
188
211
  doc = do_find.first
189
212
  @klass.new( **doc ) if doc
@@ -200,8 +223,7 @@ module Mongous
200
223
  end
201
224
 
202
225
  def delete
203
- _filter = @filter
204
- @klass.collection.delete_many( _filter )
226
+ @klass.collection.delete_many( @filter )
205
227
  end
206
228
  end
207
229
  end