monga 0.0.2 → 0.0.3
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.
- data/.gitignore +1 -0
- data/.travis.yml +1 -0
- data/README.md +59 -3
- data/lib/monga/client.rb +51 -6
- data/lib/monga/clients/master_slave_client.rb +0 -5
- data/lib/monga/clients/replica_set_client.rb +32 -71
- data/lib/monga/clients/single_instance_client.rb +53 -0
- data/lib/monga/collection.rb +102 -41
- data/lib/monga/connection.rb +38 -13
- data/lib/monga/connection_pool.rb +6 -17
- data/lib/monga/connections/buffer.rb +33 -0
- data/lib/monga/connections/em_connection.rb +25 -56
- data/lib/monga/connections/em_proxy_connection.rb +80 -0
- data/lib/monga/connections/fibered_connection.rb +26 -0
- data/lib/monga/connections/fibered_proxy_connection.rb +23 -0
- data/lib/monga/connections/proxy_connection.rb +4 -0
- data/lib/monga/connections/tcp_connection.rb +57 -0
- data/lib/monga/cursor.rb +197 -95
- data/lib/monga/database.rb +175 -60
- data/lib/monga/{requests → protocol}/delete.rb +1 -2
- data/lib/monga/{requests → protocol}/get_more.rb +1 -1
- data/lib/monga/{requests → protocol}/insert.rb +1 -2
- data/lib/monga/{requests → protocol}/kill_cursors.rb +1 -1
- data/lib/monga/{requests → protocol}/query.rb +3 -3
- data/lib/monga/{requests → protocol}/update.rb +1 -1
- data/lib/monga/request.rb +27 -23
- data/lib/monga/utils/constants.rb +5 -0
- data/lib/monga/utils/exceptions.rb +11 -0
- data/lib/monga.rb +19 -11
- data/monga.gemspec +2 -2
- data/spec/helpers/mongodb.rb +115 -38
- data/spec/monga/block/collection_spec.rb +172 -0
- data/spec/monga/block/cursor_spec.rb +160 -0
- data/spec/monga/block/database_spec.rb +80 -0
- data/spec/monga/block/single_instance_client_spec.rb +31 -0
- data/spec/monga/em/collection_spec.rb +308 -0
- data/spec/monga/em/cursor_spec.rb +256 -0
- data/spec/monga/em/database_spec.rb +140 -0
- data/spec/monga/em/replica_set_client_spec.rb +86 -0
- data/spec/monga/em/single_instance_client_spec.rb +28 -0
- data/spec/monga/sync/collection_spec.rb +247 -0
- data/spec/monga/sync/cursor_spec.rb +211 -0
- data/spec/monga/sync/database_spec.rb +110 -0
- data/spec/monga/sync/replica_set_client_spec.rb +54 -0
- data/spec/monga/sync/single_instance_client_spec.rb +25 -0
- data/spec/spec_helper.rb +2 -20
- metadata +50 -38
- data/lib/monga/clients/client.rb +0 -24
- data/lib/monga/connections/primary.rb +0 -46
- data/lib/monga/connections/secondary.rb +0 -13
- data/lib/monga/exceptions.rb +0 -9
- data/lib/monga/miner.rb +0 -72
- data/lib/monga/response.rb +0 -11
- data/spec/helpers/truncate.rb +0 -15
- data/spec/monga/collection_spec.rb +0 -448
- data/spec/monga/connection_pool_spec.rb +0 -50
- data/spec/monga/connection_spec.rb +0 -64
- data/spec/monga/cursor_spec.rb +0 -186
- data/spec/monga/database_spec.rb +0 -67
- data/spec/monga/replica_set_client_spec.rb +0 -46
- data/spec/monga/requests/delete_spec.rb +0 -0
- data/spec/monga/requests/insert_spec.rb +0 -0
- data/spec/monga/requests/query_spec.rb +0 -28
data/lib/monga/cursor.rb
CHANGED
@@ -1,69 +1,63 @@
|
|
1
1
|
module Monga
|
2
|
-
class Cursor
|
2
|
+
class Cursor
|
3
3
|
attr_reader :cursor_id
|
4
4
|
|
5
|
+
def self.create(connection, db_name, collection_name, options = {}, flags = {})
|
6
|
+
if connection.type == :em
|
7
|
+
CallbackCursor.new(connection, db_name, collection_name, options, flags)
|
8
|
+
else
|
9
|
+
BlockCursor.new(connection, db_name, collection_name, options, flags)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
5
13
|
CURSORS = {}
|
6
14
|
CLOSED_CURSOR = 0
|
7
15
|
# Batch kill cursors marked to be killed each CLOSE_TIMEOUT seconds
|
8
16
|
CLOSE_TIMEOUT = 1
|
9
17
|
|
10
|
-
def initialize(
|
11
|
-
@
|
12
|
-
|
13
|
-
@db = db
|
14
|
-
@connection = @db.client.aquire_connection
|
18
|
+
def initialize(connection, db_name, collection_name, options = {}, flags = {})
|
19
|
+
@connection = connection
|
20
|
+
@db_name = db_name
|
15
21
|
@collection_name = collection_name
|
16
22
|
@options = options
|
17
23
|
@options.merge!(flags)
|
18
24
|
|
19
25
|
@fetched_docs = []
|
20
26
|
@count = 0
|
21
|
-
|
22
|
-
@
|
23
|
-
@batch_size = @options[:batch_size]
|
27
|
+
|
28
|
+
@options[:limit] ||= 0
|
24
29
|
end
|
25
30
|
|
26
|
-
def
|
27
|
-
|
28
|
-
if doc = @fetched_docs.shift
|
29
|
-
resp.succeed doc
|
30
|
-
else
|
31
|
-
req = next_batch
|
32
|
-
req.callback do |docs|
|
33
|
-
@fetched_docs = docs
|
34
|
-
if doc = @fetched_docs.shift
|
35
|
-
@count =+ 1
|
36
|
-
resp.succeed doc
|
37
|
-
end
|
38
|
-
end
|
39
|
-
req.errback{ |err| resp.fail err }
|
40
|
-
end
|
41
|
-
end
|
31
|
+
def flag(opt)
|
32
|
+
@options.merge!(opt) and self
|
42
33
|
end
|
43
34
|
|
44
|
-
def
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
35
|
+
def limit(val)
|
36
|
+
@options[:limit] = val and self
|
37
|
+
end
|
38
|
+
|
39
|
+
def skip(val)
|
40
|
+
@options[:skip] = val and self
|
41
|
+
end
|
42
|
+
|
43
|
+
def batch_size(val)
|
44
|
+
@options[:batch_size] = val and self
|
45
|
+
end
|
46
|
+
|
47
|
+
def explain
|
48
|
+
@options[:explain] = true and self
|
49
|
+
end
|
50
|
+
|
51
|
+
def hint
|
52
|
+
@options[:hint] = true and self
|
53
|
+
end
|
54
|
+
|
55
|
+
def sort(val)
|
56
|
+
@options[:sort] = val and self
|
63
57
|
end
|
64
58
|
|
65
59
|
def kill
|
66
|
-
return
|
60
|
+
return if @cursor_id == CLOSED_CURSOR
|
67
61
|
self.class.kill_cursors(@connection, @cursor_id)
|
68
62
|
CURSORS.delete @cursor_id
|
69
63
|
@cursor_id = 0
|
@@ -75,7 +69,7 @@ module Monga
|
|
75
69
|
if cursor_ids.any?
|
76
70
|
Monga.logger.debug("Following cursors are going to be deleted: #{cursor_ids}")
|
77
71
|
kill_cursors(conn, cursor_ids)
|
78
|
-
|
72
|
+
cursor_ids.each{ |id| CURSORS.delete id }
|
79
73
|
end
|
80
74
|
end
|
81
75
|
|
@@ -85,56 +79,36 @@ module Monga
|
|
85
79
|
@cursor_id = 0
|
86
80
|
end
|
87
81
|
|
88
|
-
# Cursor is alive and we need more minerals
|
89
|
-
def more?
|
90
|
-
alive? && !satisfied?
|
91
|
-
end
|
92
|
-
|
93
82
|
private
|
94
83
|
|
95
|
-
def get_more(batch_size)
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
84
|
+
def get_more(batch_size, &block)
|
85
|
+
blk = proc do |err, data|
|
86
|
+
if err
|
87
|
+
mark_to_kill
|
88
|
+
block.call(err)
|
100
89
|
else
|
101
|
-
Monga::Requests::Query.new(@db, @collection_name, @options).callback_perform
|
102
|
-
end
|
103
|
-
req.callback do |data|
|
104
90
|
@cursor_id = data[5]
|
105
91
|
fetched_docs = data.last
|
106
|
-
@
|
107
|
-
mark_to_kill unless
|
108
|
-
|
109
|
-
resp.succeed fetched_docs
|
110
|
-
end
|
111
|
-
req.errback do |err|
|
112
|
-
mark_to_kill
|
113
|
-
resp.fail err
|
92
|
+
@count += fetched_docs.count
|
93
|
+
mark_to_kill unless more?
|
94
|
+
block.call(nil, fetched_docs, more?)
|
114
95
|
end
|
115
96
|
end
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
if more?
|
121
|
-
batch_size = get_batch_size
|
122
|
-
req = get_more(batch_size)
|
123
|
-
req.callback{ |res| resp.succeed res }
|
124
|
-
req.errback{ |err| resp.fail err }
|
97
|
+
if @cursor_id
|
98
|
+
if @cursor_id == CLOSED_CURSOR
|
99
|
+
err = Monga::Exceptions::ClosedCursor.new "You are trying to use closed cursor"
|
100
|
+
block.call(err)
|
125
101
|
else
|
126
|
-
|
127
|
-
|
128
|
-
resp.fail Monga::Exceptions::CursorIsClosed.new("Cursor is already closed. Check `cursor.more?` before calling cursor")
|
129
|
-
elsif satisfied?
|
130
|
-
resp.fail Monga::Exceptions::CursorLimit.new("You've already fetched #{@limit} docs you asked. Check `cursor.more?` before calling cursor")
|
131
|
-
end
|
102
|
+
opts = @options.merge(cursor_id: @cursor_id, batch_size: batch_size)
|
103
|
+
Monga::Protocol::GetMore.new(@connection, @db_name, @collection_name, opts).callback_perform(&blk)
|
132
104
|
end
|
105
|
+
else
|
106
|
+
Monga::Protocol::Query.new(@connection, @db_name, @collection_name, @options).callback_perform(&blk)
|
133
107
|
end
|
134
108
|
end
|
135
109
|
|
136
|
-
def
|
137
|
-
alive? && !
|
110
|
+
def more?
|
111
|
+
alive? && !satisfied?
|
138
112
|
end
|
139
113
|
|
140
114
|
# If cursor_id is not setted, or if isn't CLOSED_CURSOR - cursor is alive
|
@@ -146,30 +120,158 @@ module Monga
|
|
146
120
|
# we will be satisfied when we will get limit amount of documents.
|
147
121
|
# Otherwise we are not satisfied untill crsor is alive
|
148
122
|
def satisfied?
|
149
|
-
@limit > 0 && @count >= @limit
|
150
|
-
end
|
151
|
-
|
152
|
-
def cursor_satisfied?
|
153
|
-
@limit > 0 && @total_count >= @limit
|
123
|
+
@options[:limit] > 0 && @count >= @options[:limit]
|
154
124
|
end
|
155
125
|
|
156
126
|
# How many docs should be returned
|
157
127
|
def rest
|
158
|
-
@limit - @count if @limit > 0
|
128
|
+
@options[:limit] - @count if @options[:limit] > 0
|
159
129
|
end
|
160
130
|
|
161
131
|
# Cursor will get exact amount of docs as user passed with `limit` opr
|
162
132
|
def get_batch_size
|
163
|
-
if @limit > 0 && @batch_size
|
164
|
-
rest < @batch_size ? rest : @batch_size
|
165
|
-
else @batch_size
|
166
|
-
@batch_size
|
133
|
+
if @options[:limit] > 0 && @options[:batch_size]
|
134
|
+
rest < @options[:batch_size] ? rest : @options[:batch_size]
|
135
|
+
else @options[:batch_size]
|
136
|
+
@options[:batch_size]
|
167
137
|
end
|
168
138
|
end
|
169
139
|
|
170
140
|
def self.kill_cursors(connection, cursor_ids)
|
171
|
-
Monga::
|
141
|
+
Monga::Protocol::KillCursors.new(connection, cursor_ids: [*cursor_ids]).perform
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
class CallbackCursor < Cursor
|
146
|
+
def next_batch
|
147
|
+
get_more(get_batch_size) do |err, batch, more|
|
148
|
+
if block_given?
|
149
|
+
yield(err, batch, more)
|
150
|
+
else
|
151
|
+
err ? raise(err) : [batch, more]
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def each_batch(&blk)
|
157
|
+
iterator = Proc.new do
|
158
|
+
next_batch do |err, batch, more|
|
159
|
+
more ? blk.call(err, batch, iterator) : blk.call(err, batch)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
class << iterator
|
163
|
+
alias :next :call
|
164
|
+
end
|
165
|
+
iterator.next
|
166
|
+
end
|
167
|
+
|
168
|
+
def next_doc
|
169
|
+
if doc = @fetched_docs.shift
|
170
|
+
block_given? ? yield(nil, doc, more?) : [doc, more?]
|
171
|
+
else
|
172
|
+
get_more(get_batch_size) do |err, batch, more|
|
173
|
+
if err
|
174
|
+
block_given? ? yield(err, nil, false) : raise(err)
|
175
|
+
else
|
176
|
+
@fetched_docs = batch
|
177
|
+
doc = @fetched_docs.shift
|
178
|
+
m = more || @fetched_docs.any?
|
179
|
+
block_given? ? yield(err, doc, m) : [doc, m]
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
alias :next_document :next_doc
|
185
|
+
|
186
|
+
def each_doc(&blk)
|
187
|
+
iterator = Proc.new do
|
188
|
+
next_doc do |err, doc, more|
|
189
|
+
more ? blk.call(err, doc, iterator) : blk.call(err, doc)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
class << iterator
|
193
|
+
alias :next :call
|
194
|
+
end
|
195
|
+
iterator.next
|
196
|
+
end
|
197
|
+
alias :each_document :each_doc
|
198
|
+
|
199
|
+
def all
|
200
|
+
documents = []
|
201
|
+
each_batch do |err, batch, iter|
|
202
|
+
if err
|
203
|
+
block_given? ? yield(err) : raise(err)
|
204
|
+
else
|
205
|
+
documents += batch
|
206
|
+
if iter
|
207
|
+
iter.next
|
208
|
+
else
|
209
|
+
block_given? ? yield(nil, documents) : documents
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
172
213
|
end
|
173
214
|
|
215
|
+
def first
|
216
|
+
limit(1).all do |err, resp|
|
217
|
+
if err
|
218
|
+
block_given? ? yield(err) : raise(err)
|
219
|
+
else
|
220
|
+
block_given? ? yield(nil, resp.first) : resp.first
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
class BlockCursor < Cursor
|
227
|
+
def next_batch
|
228
|
+
get_more(get_batch_size) do |err, batch, more|
|
229
|
+
raise(err) if err
|
230
|
+
return [batch, more]
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
def each_batch(&blk)
|
235
|
+
begin
|
236
|
+
batch, more = next_batch
|
237
|
+
yield batch
|
238
|
+
end while more
|
239
|
+
end
|
240
|
+
|
241
|
+
def next_doc
|
242
|
+
if doc = @fetched_docs.shift
|
243
|
+
[doc, more?]
|
244
|
+
else
|
245
|
+
get_more(get_batch_size) do |err, batch, more|
|
246
|
+
raise(err) if err
|
247
|
+
@fetched_docs = batch
|
248
|
+
doc = @fetched_docs.shift
|
249
|
+
m = more || @fetched_docs.any?
|
250
|
+
return [doc, m]
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
alias :next_document :next_doc
|
255
|
+
|
256
|
+
def each_doc
|
257
|
+
begin
|
258
|
+
doc, more = next_doc
|
259
|
+
yield doc
|
260
|
+
end while more
|
261
|
+
end
|
262
|
+
alias :each_document :each_doc
|
263
|
+
|
264
|
+
def all
|
265
|
+
documents = []
|
266
|
+
each_batch do |batch|
|
267
|
+
documents += batch
|
268
|
+
end
|
269
|
+
documents
|
270
|
+
end
|
271
|
+
|
272
|
+
def first
|
273
|
+
resp = limit(1).all
|
274
|
+
resp.first
|
275
|
+
end
|
174
276
|
end
|
175
277
|
end
|
data/lib/monga/database.rb
CHANGED
@@ -7,90 +7,205 @@ module Monga
|
|
7
7
|
@name = name
|
8
8
|
end
|
9
9
|
|
10
|
-
|
10
|
+
# Choose collection to work
|
11
|
+
#
|
12
|
+
# client = Monga:::Client.new
|
13
|
+
# db = client.get_db("dbTest")
|
14
|
+
# collection = db.get_collection("testCollection")
|
15
|
+
# # same as
|
16
|
+
# collection = db["testCollection"]
|
17
|
+
#
|
18
|
+
def get_collection(collection_name)
|
11
19
|
Monga::Collection.new(self, collection_name)
|
12
20
|
end
|
21
|
+
alias :[] :get_collection
|
13
22
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
23
|
+
# Run some command
|
24
|
+
#
|
25
|
+
# cmd = { getLastError: 1 }
|
26
|
+
# db.cmd(cmd){ |err, resp| ... }
|
27
|
+
#
|
28
|
+
def cmd(cmd, resp_blk = nil, &ret_blk)
|
29
|
+
if resp_blk
|
30
|
+
run_cmd(cmd, ret_blk, &resp_blk)
|
31
|
+
else
|
32
|
+
run_cmd(cmd, ret_blk)
|
33
|
+
end
|
19
34
|
end
|
20
35
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
36
|
+
# Evaluate some raw javascript
|
37
|
+
#
|
38
|
+
# db.eval("return('Hello World!')") do |err, resp|
|
39
|
+
# # processing
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
def eval(js, &blk)
|
43
|
+
cmd = {}
|
44
|
+
cmd[:eval] = js
|
45
|
+
run_cmd(cmd, blk)
|
25
46
|
end
|
26
47
|
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
48
|
+
# You should be cearfull with this method 'cause it is importaint to know
|
49
|
+
# in wich connection you are trying to get last error information.
|
50
|
+
# So be happy to use safe_* methods and it will choose right connection for you.
|
51
|
+
# Or, if you really want to do it mannually:
|
52
|
+
#
|
53
|
+
# request = collection.insert({ title: "Test" })
|
54
|
+
# conn = request.connection
|
55
|
+
# db.get_last_error(conn){ |err, resp| ... }
|
56
|
+
# db.get_last_error(conn){ |err, resp| ... }
|
57
|
+
# # you should pass following options:
|
58
|
+
# db.get_last_error(
|
59
|
+
# conn,
|
60
|
+
# j: true,
|
61
|
+
# w: 2,
|
62
|
+
# fsync: true,
|
63
|
+
# wtimout: 100){ |err, resp| ... }
|
64
|
+
#
|
65
|
+
def get_last_error(connection, opts = {}, &blk)
|
66
|
+
raise_last_error(connection, opts, &blk)
|
67
|
+
rescue => e
|
68
|
+
return e
|
34
69
|
end
|
35
70
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
71
|
+
# Instead of get_last_eror this one will actually raise it.
|
72
|
+
# It is usefull for safe_* methods who should raise an error if something goes wrong
|
73
|
+
#
|
74
|
+
def raise_last_error(connection, opts = {}, &blk)
|
75
|
+
cmd = {}
|
76
|
+
cmd[:getLastError] = 1
|
77
|
+
cmd[:connection] = connection
|
78
|
+
cmd.merge!(opts)
|
79
|
+
run_cmd(cmd, blk)
|
40
80
|
end
|
41
81
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
82
|
+
# Obviously dropping collection
|
83
|
+
# There is collection#drop helper exists
|
84
|
+
#
|
85
|
+
# db.drop_collection("testCollection"){ |err, resp| ... }
|
86
|
+
# # same as
|
87
|
+
# collection = db["testCollection"]
|
88
|
+
# collection.drop{ |err, resp| ... }
|
89
|
+
#
|
90
|
+
def drop_collection(collection_name, &blk)
|
91
|
+
cmd = {}
|
92
|
+
cmd[:drop] = collection_name
|
93
|
+
run_cmd(cmd, blk)
|
46
94
|
end
|
47
95
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
96
|
+
# Create collection.
|
97
|
+
#
|
98
|
+
# db.create_collection("myCollection"){ |err, resp| ... }
|
99
|
+
# db.create_collection("myCappedCollection", capped: true, size: 1024*10){ |err, resp| ... }
|
100
|
+
#
|
101
|
+
def create_collection(collection_name, opts = {}, &blk)
|
102
|
+
cmd = {}
|
103
|
+
cmd[:create] = collection_name
|
104
|
+
cmd.merge!(opts)
|
105
|
+
run_cmd(cmd, blk)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Counts amount of documents in collection
|
109
|
+
#
|
110
|
+
# db.count("myCollection"){ |err, cnt| ... }
|
111
|
+
# # same as
|
112
|
+
# collection = db["myCollection"]
|
113
|
+
# collection.count{ |err, cnt| ... }
|
114
|
+
#
|
115
|
+
def count(collection_name, opts = {}, &blk)
|
116
|
+
cmd = {}
|
117
|
+
cmd[:count] = collection_name
|
118
|
+
cmd.merge!(opts)
|
119
|
+
run_cmd(cmd, blk) do |resp|
|
120
|
+
resp["n"].to_i
|
58
121
|
end
|
59
122
|
end
|
60
123
|
|
61
|
-
|
62
|
-
|
63
|
-
|
124
|
+
# Drop choosen indexes.
|
125
|
+
# There is collection#drop_index and collection#drop_indexes methods available
|
126
|
+
#
|
127
|
+
# db.drop_indexes("myCollection", { title: 1 })
|
128
|
+
# db.drop_indexes("myCollection", [{ title: 1 }, { author: 1 }])
|
129
|
+
# # drop all indexes
|
130
|
+
# db.drop_indexes("myCollection", "*")
|
131
|
+
# # same as
|
132
|
+
# collection = db["myCollection"]
|
133
|
+
# collection.drop_index(title: 1)
|
134
|
+
# # drop all indexes
|
135
|
+
# collection.drop_indexes
|
136
|
+
#
|
137
|
+
def drop_indexes(collection_name, indexes, &blk)
|
138
|
+
cmd = {}
|
139
|
+
cmd[:dropIndexes] = collection_name
|
140
|
+
cmd[:index] = indexes
|
141
|
+
run_cmd(cmd, blk)
|
142
|
+
end
|
143
|
+
|
144
|
+
def map_reduce
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
def aggregate
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
# Just helper to show all list of collections
|
153
|
+
#
|
154
|
+
# db.list_collections{ |err, list| ... }
|
155
|
+
#
|
156
|
+
def list_collections(&blk)
|
157
|
+
eval("db.getCollectionNames()", &blk)
|
158
|
+
end
|
159
|
+
|
160
|
+
private
|
161
|
+
|
162
|
+
# Underlying command sending
|
163
|
+
#
|
164
|
+
def run_cmd(cmd, ret_blk, &resp_blk)
|
165
|
+
connection = cmd.delete :connection
|
166
|
+
connection ||= @client.aquire_connection
|
167
|
+
|
168
|
+
options = {}
|
169
|
+
options[:query] = cmd
|
170
|
+
|
171
|
+
Monga::CallbackCursor.new(connection, name, "$cmd", options).first do |err, resp|
|
172
|
+
res = make_response(err, resp, ret_blk, resp_blk)
|
173
|
+
return res unless ret_blk
|
64
174
|
end
|
65
175
|
end
|
66
176
|
|
67
|
-
#
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
177
|
+
# Helper to choose how to return result.
|
178
|
+
# If callback is provided it will be passed there.
|
179
|
+
# Otherwise error will be raised and result will be returned with a `return`
|
180
|
+
#
|
181
|
+
def make_response(err, resp, ret_blk, resp_blk)
|
182
|
+
err, resp = check_response(err, resp)
|
183
|
+
if err
|
184
|
+
if ret_blk
|
185
|
+
ret_blk.call(err, resp)
|
186
|
+
else
|
187
|
+
raise err
|
73
188
|
end
|
74
|
-
|
75
|
-
|
189
|
+
else
|
190
|
+
resp = resp_blk.call(resp) if resp_blk
|
191
|
+
if ret_blk
|
192
|
+
ret_blk.call(err, resp)
|
193
|
+
else
|
194
|
+
resp
|
76
195
|
end
|
77
196
|
end
|
78
197
|
end
|
79
198
|
|
80
|
-
|
81
|
-
|
82
|
-
def
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
resp.fail(exception)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
req.errback{ |err| resp.fail err }
|
199
|
+
# Blank result should be interpreted as an error. Ok so.
|
200
|
+
#
|
201
|
+
def check_response(err, data)
|
202
|
+
if err
|
203
|
+
[err, data]
|
204
|
+
elsif data.nil? || data.empty?
|
205
|
+
error = Monga::Exceptions::QueryFailure.new("Empty Response is not a valid Response")
|
206
|
+
[error, data]
|
207
|
+
else
|
208
|
+
[nil, data]
|
94
209
|
end
|
95
210
|
end
|
96
211
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module Monga::
|
1
|
+
module Monga::Protocol
|
2
2
|
class Query < Monga::Request
|
3
3
|
op_name :query
|
4
4
|
|
@@ -15,7 +15,7 @@ module Monga::Requests
|
|
15
15
|
@body ||= begin
|
16
16
|
skip = @options[:skip] || 0
|
17
17
|
limit = get_limit
|
18
|
-
|
18
|
+
selector = @options[:selector] || {}
|
19
19
|
|
20
20
|
query = {}
|
21
21
|
query["$query"] = @options[:query] || {}
|
@@ -29,7 +29,7 @@ module Monga::Requests
|
|
29
29
|
b.put_int(skip)
|
30
30
|
b.put_int(limit)
|
31
31
|
b.append!(BSON::BSON_C.serialize(query).to_s)
|
32
|
-
b.append!(BSON::BSON_C.serialize(
|
32
|
+
b.append!(BSON::BSON_C.serialize(selector).to_s) if selector.any?
|
33
33
|
b
|
34
34
|
end
|
35
35
|
end
|