mongous 0.1.5 → 0.3.0

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 (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