mongous 0.2.1 → 0.4.4

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