mongous 0.1.5 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +216 -44
  3. data/README.ja.adoc +217 -45
  4. data/lib/mongous/base.rb +30 -0
  5. data/lib/mongous/document.rb +75 -32
  6. data/lib/mongous/extention.rb +55 -46
  7. data/lib/mongous/filter.rb +82 -60
  8. data/lib/mongous/version.rb +1 -1
  9. data/sample/connect_auto_2.rb +2 -1
  10. data/sample/connect_default_2.rb +2 -1
  11. data/sample/connect_environ_2.rb +2 -1
  12. data/sample/connect_loadfile_2.rb +2 -1
  13. data/sample/declare_compact_1.rb +7 -7
  14. data/sample/declare_label_1.rb +10 -6
  15. data/sample/declare_ndex_1.rb +9 -5
  16. data/sample/declare_ndex_2.rb +10 -6
  17. data/sample/declare_strict_1.rb +14 -10
  18. data/sample/declare_strict_2.rb +5 -3
  19. data/sample/{multi_docs_1.rb → multi_collection_1.rb} +0 -0
  20. data/sample/multi_collection_2.rb +63 -0
  21. data/sample/multi_collection_3.rb +26 -0
  22. data/sample/query_basic_1.rb +3 -1
  23. data/sample/query_basic_2.rb +5 -3
  24. data/sample/query_basic_3.rb +2 -3
  25. data/sample/query_basic_4.rb +3 -4
  26. data/sample/query_basic_5.rb +2 -3
  27. data/sample/query_detail_1.rb +3 -1
  28. data/sample/query_detail_2.rb +3 -1
  29. data/sample/query_detail_3.rb +5 -3
  30. data/sample/{query_basic_6.rb → query_filter_1.rb} +8 -5
  31. data/sample/query_filter_2.rb +50 -0
  32. data/sample/{query_super_1.rb → query_find_1.rb} +0 -1
  33. data/sample/query_projection_1.rb +5 -8
  34. data/sample/query_skip_limit_1.rb +47 -0
  35. data/sample/query_skip_limit_2.rb +49 -0
  36. data/sample/query_sort_order_1.rb +46 -0
  37. data/sample/save_basic_1.rb +1 -2
  38. data/sample/save_basic_2.rb +1 -2
  39. data/sample/save_basic_3.rb +1 -2
  40. data/sample/save_detail_1.rb +7 -4
  41. data/sample/save_detail_2.rb +7 -4
  42. data/sample/save_detail_3.rb +11 -8
  43. data/sample/save_verify_1.rb +7 -4
  44. data/sample/save_verify_3.rb +1 -1
  45. data/sample/save_verify_5.rb +3 -3
  46. data/sample/save_verify_6.rb +3 -3
  47. data/sample/save_verify_7.rb +23 -0
  48. data/sample/update_basic_1.rb +13 -0
  49. data/sample/zap_basic_2.rb +2 -2
  50. data/sample/zap_basic_3.rb +2 -2
  51. data/sample/zbenchmark_search_1.rb +110 -0
  52. data/sample/zbenchmark_search_2.rb +110 -0
  53. metadata +15 -10
  54. data/sample/multi_docs_2.rb +0 -58
  55. data/sample/query_limit_1.rb +0 -44
  56. data/sample/query_order_1.rb +0 -49
  57. data/sample/template_article.rb +0 -5
  58. data/sample/template_person.rb +0 -12
@@ -50,6 +50,36 @@ module Mongous
50
50
  self.class_variable_set( :@@client, _client )
51
51
  end
52
52
 
53
+ def attach!( *names )
54
+ raise Mongous::Error, "missing argument." if names.empty?
55
+
56
+ names.each do |name|
57
+ case name
58
+ when String
59
+ when Symbol
60
+ name = name.to_s
61
+ else
62
+ raise Mongous::Error, "type invalid. : #{ name }"
63
+ end
64
+
65
+ raise Mongous::Error, "missing argument." unless /^[A-Z]/.match(name)
66
+
67
+ if Object.const_defined?( name )
68
+ if Object.const_get( name ).include?( Mongous::Document )
69
+ Object.class_eval{ remove_const( name ) }
70
+ else
71
+ raise Mongous::Error, "type invalid. : #{ Object.class_eval(name) }"
72
+ end
73
+ end
74
+
75
+ Object.class_eval <<-CLASS
76
+ class #{name}
77
+ include Mongous::Document
78
+ end
79
+ CLASS
80
+ end
81
+ end
82
+
53
83
  def client
54
84
  self.class_variable_get( :@@client ) rescue nil
55
85
  end
@@ -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,23 +94,29 @@ 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
-
72
- self.class.collection.insert_one( @doc )
73
103
  self
74
104
  end
75
105
 
106
+ def to_hash
107
+ @doc.dup
108
+ end
109
+
110
+ def to_json
111
+ @doc.to_json
112
+ end
113
+
76
114
  def []( label )
77
115
  label = label.to_s
78
116
 
79
117
  if self.class.symbols[:strict]
80
- if !self.class.fields.keys.include?(label)
118
+ labels = ["_id"] + self.class.fields.keys
119
+ if !labels.include?( label )
81
120
  raise Mongous::Error, "undefined field. : #{ label }"
82
121
  end
83
122
  end
@@ -108,18 +147,18 @@ module Mongous
108
147
  return @doc[label] = value if field.nil?
109
148
 
110
149
  types = []
111
- if args = field[:_args] || []
112
- args.each do |arg|
113
- if arg.class == Class
114
- types << arg
115
- args -= [arg]
150
+ if attrs = field[:_attrs] || []
151
+ attrs.each do |attr|
152
+ if attr.class == Class
153
+ types << attr
154
+ attrs -= [attr]
116
155
  break
117
156
  end
118
157
  end
119
158
  end
120
159
 
121
160
  if !types.empty?
122
- if !(args & [:must, :not_null]).empty?
161
+ if !(attrs & [:must, :not_null]).empty?
123
162
  if !types.include?( value.class )
124
163
  raise Mongous::Error, "invalid type. : #{ label } : #{ value.class }"
125
164
  end
@@ -129,7 +168,7 @@ module Mongous
129
168
  end
130
169
  end
131
170
  else
132
- if !(args & [:must, :not_null]).empty?
171
+ if !(attrs & [:must, :not_null]).empty?
133
172
  if [NilClass].include?( value.class )
134
173
  raise Mongous::Error, "invalid type. : #{ label } : #{ value.class }"
135
174
  end
@@ -138,19 +177,23 @@ module Mongous
138
177
 
139
178
  @doc[label] = value
140
179
 
141
- args.each do |arg|
142
- case arg
180
+ attrs.each do |attr|
181
+ case attr
143
182
  when Proc
144
- if !self.instance_eval( &arg )
183
+ if !self.instance_eval( &attr )
145
184
  raise Mongous::Error, "violation detected. : #{ label } : #{ value }"
146
185
  end
147
186
  when Array
148
- if !arg.include?( value )
149
- raise Mongous::Error, "not include. : #{ label } :#{ value }"
187
+ if !attr.include?( value )
188
+ raise Mongous::Error, "not include. : #{ label } : #{ value }"
150
189
  end
151
190
  when Range
152
- if !arg.cover?( value )
153
- raise Mongous::Error, "out of range. : #{ label } :#{ value }"
191
+ if !attr.cover?( value )
192
+ raise Mongous::Error, "out of range. : #{ label } : #{ value }"
193
+ end
194
+ when Regexp
195
+ if !attr.match( value )
196
+ raise Mongous::Error, "unmatch regexp. : #{ label } : #{ value }"
154
197
  end
155
198
  end
156
199
  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
 
@@ -99,53 +99,62 @@ module Mongous
99
99
  self.collection.find( conditios, options )
100
100
  end
101
101
 
102
- def field( label, *args, **opts, &block )
102
+ def field( symbol, *attrs, **items )
103
103
  m = /(.*?):(\d+)/.match( caller()[0] )
104
104
  call_from = [ m[1], m[2] ].join(":")
105
105
 
106
- args.each do |arg|
107
- if klass = arg.class
108
- if ![Class, Range, Array, Proc, Symbol].include?(klass)
109
- 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 }"
110
110
  end
111
111
  end
112
112
  end
113
113
 
114
- opts.each do |key, value|
115
- case key
116
- when :default
117
- case value
118
- when Proc, String, Numeric
119
- else
120
- raise Mongous::Error, "field error. : #{key} on #{ label } at #{ call_from }"
121
- end
122
- 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 }"
123
118
  end
124
119
 
125
- opts[:_args] = args
126
- opts[:_block] = block
127
- fields[label.to_s] = opts
120
+ items[:_attrs] = attrs
121
+ fields[symbol.to_s] = items
128
122
  end
129
123
 
130
- def verify( *syms, &block )
131
- if !syms.empty?
132
- syms.each do |sym|
133
- symbols[sym] = true
124
+ def verify( *directives, &block )
125
+ if !directives.empty?
126
+ directives.each do |directive|
127
+ symbols[directive] = true
134
128
  end
135
129
  elsif block
136
130
  m = /(.*?):(\d+)/.match( caller()[0] )
137
131
  call_from = [ m[1], m[2] ].join(":")
138
132
  blocks[call_from] = block
133
+ else
134
+ raise Mongous::Error, "'verify' arguments error. need directives or block."
139
135
  end
140
136
  end
141
137
 
142
- def index( *syms, **opts )
143
- opts[:background] = true unless opts.has_key?(:background)
138
+ def index( *symbols, **options )
139
+ options[:background] = true unless options.has_key?(:background)
144
140
  keys = {}
145
- syms.each do |sym|
146
- 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 }"
147
157
  end
148
- indexes.push << [keys, opts]
149
158
  end
150
159
  end
151
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