mongous 0.2.1 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +73 -0
  3. data/README.adoc +176 -26
  4. data/README.ja.adoc +176 -26
  5. data/Rakefile +8 -8
  6. data/_Gemfile.lock +38 -0
  7. data/lib/mongous/base.rb +52 -8
  8. data/lib/mongous/document.rb +21 -10
  9. data/lib/mongous/extention.rb +45 -35
  10. data/lib/mongous/filter.rb +316 -230
  11. data/lib/mongous/version.rb +1 -1
  12. data/mongous.gemspec +4 -4
  13. data/sample/connect_auto_0.rb +9 -0
  14. data/sample/declare_compact_1.rb +5 -8
  15. data/sample/declare_compact_2.rb +38 -0
  16. data/sample/declare_label_1.rb +7 -7
  17. data/sample/declare_ndex_1.rb +6 -6
  18. data/sample/declare_ndex_2.rb +7 -7
  19. data/sample/declare_strict_1.rb +2 -4
  20. data/sample/declare_strict_2.rb +2 -4
  21. data/sample/multi_collection_1.rb +0 -2
  22. data/sample/multi_collection_2.rb +0 -2
  23. data/sample/multi_collection_3.rb +24 -0
  24. data/sample/query_basic_1.rb +10 -4
  25. data/sample/query_basic_2.rb +10 -4
  26. data/sample/query_basic_3.rb +0 -2
  27. data/sample/query_basic_4.rb +0 -2
  28. data/sample/query_basic_5.rb +0 -2
  29. data/sample/query_basic_6.rb +56 -0
  30. data/sample/query_detail_1.rb +2 -3
  31. data/sample/query_detail_2.rb +2 -3
  32. data/sample/query_detail_3.rb +0 -2
  33. data/sample/query_filter_1.rb +0 -2
  34. data/sample/query_filter_2.rb +0 -2
  35. data/sample/query_find_1.rb +14 -13
  36. data/sample/query_select_1.rb +54 -0
  37. data/sample/query_skip_limit_1.rb +17 -16
  38. data/sample/query_skip_limit_2.rb +19 -10
  39. data/sample/query_sort_1.rb +43 -0
  40. data/sample/save_basic_1.rb +1 -5
  41. data/sample/save_basic_2.rb +1 -5
  42. data/sample/save_basic_3.rb +1 -5
  43. data/sample/save_detail_1.rb +0 -2
  44. data/sample/save_detail_2.rb +0 -2
  45. data/sample/save_detail_3.rb +5 -7
  46. data/sample/save_verify_1.rb +2 -4
  47. data/sample/save_verify_2.rb +0 -2
  48. data/sample/save_verify_3.rb +0 -2
  49. data/sample/save_verify_4.rb +0 -2
  50. data/sample/save_verify_5.rb +0 -2
  51. data/sample/save_verify_6.rb +0 -2
  52. data/sample/save_verify_7.rb +0 -2
  53. data/sample/update_basic_1.rb +1 -5
  54. data/sample/zap_basic_1.rb +1 -5
  55. data/sample/zap_basic_2.rb +2 -6
  56. data/sample/zap_basic_3.rb +7 -0
  57. data/sample/zbenchmark_search_1.rb +114 -0
  58. data/sample/zbenchmark_search_2.rb +114 -0
  59. data/sample/zbenchmark_search_3.rb +88 -0
  60. metadata +31 -22
  61. data/.travis.yml +0 -6
  62. data/sample/query_projection_1.rb +0 -41
  63. data/sample/query_sort_order_1.rb +0 -46
data/Rakefile CHANGED
@@ -13,7 +13,7 @@ class Bundler::GemHelper
13
13
  dest_path = File.join(dir, "#{name}-#{version}.zip")
14
14
  cmnd = "git archive --format zip --prefix=#{name}/ HEAD > #{dest_path}"
15
15
 
16
- out, code = sh_with_status( cmnd )
16
+ _, code = sh_with_status( cmnd )
17
17
  raise "Couldn't archive gem," unless code == 0
18
18
 
19
19
  Bundler.ui.confirm "#{name} #{version} archived to #{dest_path}."
@@ -23,11 +23,11 @@ class Bundler::GemHelper
23
23
  ver = version.to_s
24
24
 
25
25
  cmnd = "git push origin #{ver} "
26
- out, code = sh_with_status( cmnd )
26
+ _, code = sh_with_status( cmnd )
27
27
  raise "Couldn't git push origin." unless code == 0
28
28
 
29
29
  cmnd = "git push "
30
- out, code = sh_with_status( cmnd )
30
+ _, code = sh_with_status( cmnd )
31
31
  raise "Couldn't git push." unless code == 0
32
32
 
33
33
  Bundler.ui.confirm "Git Push #{ver}."
@@ -43,15 +43,15 @@ class Bundler::GemHelper
43
43
  end
44
44
 
45
45
  cmnd = "git add #{version_pathname} "
46
- out, code = sh_with_status( cmnd )
46
+ _, code = sh_with_status( cmnd )
47
47
  raise "Couldn't git add," unless code == 0
48
48
 
49
49
  cmnd = "git commit -m '#{new_version}' "
50
- out, code = sh_with_status( cmnd )
50
+ _, code = sh_with_status( cmnd )
51
51
  raise "Couldn't git commit." unless code == 0
52
52
 
53
53
  cmnd = "git tag #{new_version} "
54
- out, code = sh_with_status( cmnd )
54
+ _, code = sh_with_status( cmnd )
55
55
  raise "Couldn't git tag." unless code == 0
56
56
 
57
57
  Bundler.ui.confirm "Update Tags to #{new_version}."
@@ -80,14 +80,14 @@ Bundler::GemHelper.new(Dir.pwd).instance_eval do
80
80
 
81
81
  desc "Update Version Minor"
82
82
  task 'minor' do
83
- major, minor, tiny = version.to_s.split('.')
83
+ major, minor, _tiny = version.to_s.split('.')
84
84
  new_version = [major, minor.to_i + 1, 0].join('.')
85
85
  update_version( new_version )
86
86
  end
87
87
 
88
88
  desc "Update Version Major"
89
89
  task 'major' do
90
- major, minor, tiny = version.to_s.split('.')
90
+ major, _minor, _tiny = version.to_s.split('.')
91
91
  new_version = [major.to_i + 1, 0, 0].join('.')
92
92
  update_version( new_version )
93
93
  end
@@ -0,0 +1,38 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ mongous (0.4.3)
5
+ mongo
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ bson (4.11.1)
11
+ diff-lcs (1.4.4)
12
+ mongo (2.14.0)
13
+ bson (>= 4.8.2, < 5.0.0)
14
+ rake (13.0.3)
15
+ rspec (3.10.0)
16
+ rspec-core (~> 3.10.0)
17
+ rspec-expectations (~> 3.10.0)
18
+ rspec-mocks (~> 3.10.0)
19
+ rspec-core (3.10.1)
20
+ rspec-support (~> 3.10.0)
21
+ rspec-expectations (3.10.1)
22
+ diff-lcs (>= 1.2.0, < 2.0)
23
+ rspec-support (~> 3.10.0)
24
+ rspec-mocks (3.10.1)
25
+ diff-lcs (>= 1.2.0, < 2.0)
26
+ rspec-support (~> 3.10.0)
27
+ rspec-support (3.10.1)
28
+
29
+ PLATFORMS
30
+ x86_64-linux
31
+
32
+ DEPENDENCIES
33
+ mongous!
34
+ rake
35
+ rspec
36
+
37
+ BUNDLED WITH
38
+ 2.2.6
@@ -11,7 +11,7 @@ module Mongous
11
11
  def connect( hosts_or_uri = nil, file: nil, mode: nil, loglevel: nil, **options )
12
12
  case hosts_or_uri
13
13
  when Array, String
14
- ;
14
+ hosts_or_uri
15
15
 
16
16
  when NilClass
17
17
  if file
@@ -46,19 +46,63 @@ module Mongous
46
46
  end
47
47
 
48
48
  def connect!( hosts_or_uri = nil, **options )
49
- _client = connect( hosts_or_uri, **options )
50
- self.class_variable_set( :@@client, _client )
49
+ client_ = connect( hosts_or_uri, **options )
50
+ self.class_variable_set( :@@client, client_ )
51
51
  end
52
52
 
53
+ def document!( *names, **opts )
54
+ raise Mongous::Error, "missing argument." if names.empty?
55
+
56
+ names.each do |name|
57
+ case name
58
+ when String
59
+ name
60
+ when Symbol
61
+ name = name.to_s
62
+ else
63
+ raise Mongous::Error, "type invalid. : #{ name }"
64
+ end
65
+
66
+ raise Mongous::Error, "missing argument." unless /^[A-Z]/.match(name)
67
+
68
+ if Object.const_defined?( name )
69
+ if Object.const_get( name ).include?( Mongous::Document )
70
+ Object.class_eval{ remove_const( name ) }
71
+ else
72
+ raise Mongous::Error, "type invalid. : #{ Object.class_eval(name) }"
73
+ end
74
+ end
75
+
76
+ klass = Object.class_eval <<-CLASS
77
+ class #{name}
78
+ include Mongous::Document
79
+ end
80
+ CLASS
81
+
82
+ if opts[:timestamp]
83
+ klass.class_eval do
84
+ field :created_at, Time, create: proc{ Time.now }
85
+ field :updated_at, Time, update: proc{ Time.now }
86
+ index :created_at
87
+ index :updated_at
88
+ end
89
+ end
90
+ end
91
+ end
92
+ alias :attach! :document!
93
+
53
94
  def client
54
- self.class_variable_get( :@@client ) rescue nil
95
+ if not self.class_variable_defined?( :@@client )
96
+ connect!
97
+ end
98
+ self.class_variable_get( :@@client )
55
99
  end
56
100
 
57
- def client=( _client )
58
- if !_client.is_a?( ::Mongo::Client )
59
- raise Mongous::Error, "type invalid. : #{ _client }"
101
+ def client=( new_client )
102
+ if not new_client.is_a?( ::Mongo::Client )
103
+ raise Mongous::Error, "type invalid. : #{ new_client }"
60
104
  end
61
- self.class_variable_set( :@@client, _client )
105
+ self.class_variable_set( :@@client, new_client )
62
106
  end
63
107
 
64
108
  def loger
@@ -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] ]
@@ -55,12 +55,12 @@ module Mongous
55
55
 
56
56
  self.class.fields.each do |label, field|
57
57
  default_value = getvalue_or_callproc( field[:default] )
58
- _must = field[:_attrs].include?(:must)
58
+ must = field[:_attrs].include?(:must)
59
59
  if @doc.has_key?(label)
60
60
  if !having?( @doc[label] )
61
61
  if default_value
62
62
  self[label] = default_value
63
- elsif _must
63
+ elsif must
64
64
  raise Mongous::Error, "must but unassigned field. : #{ label }"
65
65
  elsif self.class.symbols[:strict]
66
66
  self[label] = nil
@@ -69,7 +69,7 @@ module Mongous
69
69
  else
70
70
  if default_value
71
71
  self[label] = default_value
72
- elsif _must
72
+ elsif must
73
73
  raise Mongous::Error, "must but unassigned field. : #{ label }"
74
74
  elsif self.class.symbols[:strict]
75
75
  self[label] = nil
@@ -78,11 +78,11 @@ module Mongous
78
78
 
79
79
  case savemode
80
80
  when :create
81
- if create_value = getvalue_or_callproc( field[:create] )
81
+ if ( create_value = getvalue_or_callproc( field[:create] ) )
82
82
  self[label] = create_value
83
83
  end
84
84
  when :update
85
- if update_value = getvalue_or_callproc( field[:update] )
85
+ if ( update_value = getvalue_or_callproc( field[:update] ) )
86
86
  self[label] = update_value
87
87
  end
88
88
  end
@@ -100,15 +100,23 @@ module Mongous
100
100
  when :update
101
101
  self.class.collection.update_one( { "_id"=> @doc["_id"] }, { '$set' => @doc } )
102
102
  end
103
-
104
103
  self
105
104
  end
106
105
 
106
+ def to_hash
107
+ @doc.dup
108
+ end
109
+
110
+ def to_json( **opts )
111
+ ::JSON.generate( @doc, **opts )
112
+ end
113
+
107
114
  def []( label )
108
115
  label = label.to_s
109
116
 
110
117
  if self.class.symbols[:strict]
111
- if !(self.class.fields.keys.include?(label) || (label == "_id"))
118
+ labels = ["_id"] + self.class.fields.keys
119
+ if !labels.include?( label )
112
120
  raise Mongous::Error, "undefined field. : #{ label }"
113
121
  end
114
122
  end
@@ -136,10 +144,13 @@ module Mongous
136
144
  end
137
145
 
138
146
  field = self.class.fields[label]
139
- return @doc[label] = value if field.nil?
147
+ if field.nil?
148
+ @doc[label] = value
149
+ return
150
+ end
140
151
 
141
152
  types = []
142
- if attrs = field[:_attrs] || []
153
+ if ( attrs = field[:_attrs] || [] )
143
154
  attrs.each do |attr|
144
155
  if attr.class == Class
145
156
  types << attr
@@ -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,7 +114,7 @@ module Mongous
104
114
  call_from = [ m[1], m[2] ].join(":")
105
115
 
106
116
  attrs.each do |attr|
107
- if klass = attr.class
117
+ if ( klass = attr.class )
108
118
  if ![Class, Range, Array, Regexp, Proc, Symbol].include?(klass)
109
119
  raise Mongous::Error, "'field' arguments error. : #{ attr } on #{ symbol } at #{ call_from }"
110
120
  end
@@ -1,230 +1,316 @@
1
-
2
- module Mongous
3
- module Extention
4
- def count
5
- # self.collection.find.count
6
- self.collection.estimated_document_count
7
- end
8
-
9
- def first
10
- doc = self.collection.find.first
11
- self.new( **doc ) if doc
12
- end
13
-
14
- def all
15
- self.collection.find.map do |doc|
16
- self.new( **doc )
17
- end
18
- end
19
-
20
- def each( &block )
21
- all.each( &block )
22
- end
23
-
24
- def delete
25
- self.collection.delete_many({})
26
- end
27
-
28
- def where( filter = nil, **conditions )
29
- condition = normalize( filter, conditions )
30
- Filter.new( self ).where( condition )
31
- end
32
-
33
- def not( filter = nil, **conditions )
34
- raise Mongous::Error, "Unset args for #{self}.not." if filter.nil? && conditions.empty?
35
-
36
- condition = normalize( filter, conditions )
37
- Filter.new( self ).where({"$nor" => [condition]})
38
- end
39
-
40
- def and( *filters )
41
- raise Mongous::Error, "Unset args for #{self}.and." if filters.empty?
42
-
43
- conditions = filters.map do |filter|
44
- normalize( filter, {} )
45
- end
46
- Filter.new( self ).where({"$and" => conditions})
47
- end
48
-
49
- def or( *filters )
50
- raise Mongous::Error, "Unset args for #{self}.or." if filters.empty?
51
-
52
- conditions = filters.map do |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]
64
- when Filter
65
- _filter.to_condition
66
- when Hash
67
- _filter
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}"
74
- end
75
- end
76
- end
77
- end
78
-
79
- module Mongous
80
- class Filter
81
- def initialize( klass )
82
- @klass = klass
83
- @filter = {}
84
- @option = {}
85
- end
86
-
87
- def where( conditions )
88
- hash = {}
89
- conditions.each do |key, item|
90
- case key
91
- when /\$(and|or|nor)/
92
- hash[key] = item
93
-
94
- else
95
- case item
96
- when Array
97
- hash[key] = {"$in"=>item}
98
-
99
- when Range
100
- _begin_oper = "$gte"
101
- _end_oper = item.exclude_end? ? "$lt" : "$lte"
102
-
103
- if item.begin && item.end
104
- hash[key] = { _begin_oper => item.begin, _end_oper => item.end }
105
-
106
- elsif !item.begin && item.end
107
- hash[key] = { _end_oper => item.end }
108
-
109
- elsif item.begin && !item.end
110
- hash[key] = { _begin_oper => item.begin }
111
-
112
- else
113
- raise Mongous::Error, "invalid range. : #{ item }"
114
-
115
- end
116
-
117
- else
118
- hash[key] = item
119
-
120
- end
121
- end
122
- end
123
- @filter.merge!( hash )
124
- self.dup
125
- end
126
-
127
- def to_condition
128
- @filter.dup
129
- end
130
-
131
- def option( _option )
132
- @option.merge!( _option )
133
- self.dup
134
- end
135
-
136
- def projection( _projection )
137
- @projection = _projection
138
- self.dup
139
- end
140
- alias :select :projection
141
-
142
- def sort( _sort )
143
- @sort = _sort
144
- self.dup
145
- end
146
- alias :order :sort
147
-
148
- def []( nth_or_range, len = nil )
149
- case nth_or_range
150
- when Integer
151
- @skip = nth_or_range
152
-
153
- if len
154
- raise Mongous::Error, "invalid len. : #{ len }" if !len.is_a? Integer || len <= 0
155
- @limit = len
156
- end
157
-
158
- when Range
159
- from = nth_or_range.begin
160
- raise Mongous::Error, "invalid range. : #{ nth_or_range }" unless from.is_a? Integer
161
-
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
173
-
174
- self.dup
175
- end
176
-
177
- def do_find
178
- _filter = @filter
179
- _option = @option.dup
180
- _option[:projection] = @projection if @projection
181
- found = @klass.collection.find( _filter, _option )
182
- found = found.sort( @sort ) if @sort
183
- found = found.skip( @skip ) if @skip
184
- found = found.limit( @limit ) if @limit
185
- found
186
- end
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
-
210
- def first
211
- doc = do_find.first
212
- @klass.new( **doc ) if doc
213
- end
214
-
215
- def all
216
- do_find.map do |doc|
217
- @klass.new( **doc )
218
- end
219
- end
220
-
221
- def each( &block )
222
- all.each( &block )
223
- end
224
-
225
- def delete
226
- @klass.collection.delete_many( @filter )
227
- end
228
- end
229
- end
230
-
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
+