@@ -187,16 +187,52 @@ defmodule Mongo.BulkWrite do
187
187
one_bulk_write ( conn , bulk , write_concern , opts )
188
188
end
189
189
end
190
- def write ( topology_pid , % OrderedBulk { coll: coll , ops: ops } = bulk , opts ) do
190
+ def write ( topology_pid , % OrderedBulk { coll: coll , ops: ops } , opts ) do
191
191
192
192
write_concern = write_concern ( opts )
193
+
194
+ empty = % {
195
+ acknowledged: acknowledged ( write_concern ) ,
196
+ insertedCount: 0 ,
197
+ matchedCount: 0 ,
198
+ deletedCount: 0 ,
199
+ upsertedCount: 0 ,
200
+ modifiedCount: 0 ,
201
+ upsertedIds: [ ] ,
202
+ insertedIds: [ ] ,
203
+ }
204
+
193
205
with { :ok , conn , _ , _ } <- Mongo . select_server ( topology_pid , :write , opts ) do
206
+
194
207
get_op_sequence ( coll , ops )
195
208
|> Enum . map ( fn { cmd , docs } -> one_bulk_write_operation ( conn , cmd , coll , docs , write_concern , opts ) end )
196
- |> Enum . each ( fn { cmd , count } -> IO . puts "#{ cmd } : #{ count } " end ) # todo collect results
209
+ |> Enum . reduce ( empty , fn
210
+ { cmd , { count , ids } } , acc -> merge ( cmd , count , ids , acc )
211
+ { cmd , { mat , mod , ups , ids } } , acc -> merge ( cmd , mat , mod , ups , ids , acc )
212
+ { cmd , count } , acc -> merge ( cmd , count , acc )
213
+
214
+ end )
197
215
end
198
216
end
199
217
218
+ defp merge ( :insert , count , ids , % { :insertedCount => value , :insertedIds => current_ids } = result ) do
219
+ % { result | insertedCount: value + count , insertedIds: current_ids ++ ids }
220
+ end
221
+ defp merge ( :update , matched , modified , upserts , ids ,
222
+ % { :matchedCount => matched_count ,
223
+ :modifiedCount => modified_count ,
224
+ :upsertedCount => upserted_count ,
225
+ :upsertedIds => current_ids } = result ) do
226
+ % { result | matchedCount: matched_count + matched ,
227
+ modifiedCount: modified_count + modified ,
228
+ upsertedCount: upserted_count + upserts ,
229
+ upsertedIds: current_ids ++ ids }
230
+ end
231
+ defp merge ( :delete , count , % { :deletedCount => value } = result ) do
232
+ % { result | deletedCount: value + count }
233
+ end
234
+ defp merge ( _other , _count , result ) , do: result
235
+
200
236
##
201
237
# returns the current write concerns from `opts`
202
238
#
@@ -208,30 +244,32 @@ defmodule Mongo.BulkWrite do
208
244
} |> filter_nils ( )
209
245
end
210
246
211
- @ doc """
212
- Executues one unordered bulk write. The execution order of operation groups is
247
+ ##
248
+ # Executes one unordered bulk write. The execution order of operation groups is
249
+ #
250
+ # * inserts
251
+ # * updates
252
+ # * deletes
253
+ #
254
+ # The function returns a keyword list with the results of each operation group:
255
+ # For the details see https://github.com/mongodb/specifications/blob/master/source/crud/crud.rst#results
256
+ defp one_bulk_write ( conn , % UnorderedBulk { coll: coll , inserts: inserts , updates: updates , deletes: deletes } , write_concern , opts ) do
213
257
214
- * inserts
215
- * updates
216
- * deletes
258
+ with { _ , { inserts , ids } } <- one_bulk_write_operation ( conn , :insert , coll , inserts , write_concern , opts ) ,
259
+ { _ , { matched , modified , upserts , upsert_ids } } <- one_bulk_write_operation ( conn , :update , coll , updates , write_concern , opts ) ,
260
+ { _ , deletes } <- one_bulk_write_operation ( conn , :delete , coll , deletes , write_concern , opts ) do
217
261
218
- The function returns a keyword list with the results of each operation group:
219
- For the details see https://github.com/mongodb/specifications/blob/master/source/crud/crud.rst#results
220
- """
221
- defp one_bulk_write ( conn , % UnorderedBulk { coll: coll , inserts: inserts , updates: updates , deletes: deletes } = bulk , write_concern , opts ) do
222
262
223
- with { _ , inserts } <- one_bulk_write_operation ( conn , :insert , coll , inserts , write_concern , opts ) ,
224
- { _ , updates } <- one_bulk_write_operation ( conn , :update , coll , updates , write_concern , opts ) ,
225
- { _ , deletes } <- one_bulk_write_operation ( conn , :delete , coll , deletes , write_concern , opts ) do
226
- [
263
+ % {
227
264
acknowledged: acknowledged ( write_concern ) ,
228
265
insertedCount: inserts ,
229
- matchedCount: updates ,
266
+ insertedIds: ids ,
267
+ matchedCount: matched ,
230
268
deletedCount: deletes ,
231
- upsertedCount: 0 ,
232
- upsertedIds: [ ] ,
233
- insertedIds: [ ] ,
234
- ]
269
+ modifiedCount: modified ,
270
+ upsertedCount: upserts ,
271
+ upsertedIds: upsert_ids
272
+ }
235
273
end
236
274
end
237
275
@@ -262,7 +300,7 @@ defmodule Mongo.BulkWrite do
262
300
defp get_op_sequence ( coll , ops ) do
263
301
get_op_sequence ( coll , ops , [ ] )
264
302
end
265
- defp get_op_sequence ( coll , [ ] , acc ) , do: acc
303
+ defp get_op_sequence ( _coll , [ ] , acc ) , do: acc
266
304
defp get_op_sequence ( coll , ops , acc ) do
267
305
[ { kind , _doc } | _rest ] = ops
268
306
{ docs , rest } = find_max_sequence ( kind , ops )
@@ -287,71 +325,72 @@ defmodule Mongo.BulkWrite do
287
325
{ acc , rest }
288
326
end
289
327
290
- # {
291
- #"acknowledged" : true,
292
- #"deletedCount" : 1,
293
- #"insertedCount" : 2,
294
- # "matchedCount" : 2,
295
- #"upsertedCount" : 0,
296
- #"insertedIds" : {
297
- # "0" : 4,
298
- #"1" : 5
299
- #},
300
- #"upsertedIds" : {
301
- #
302
- # }
303
- # }
304
-
305
- defp collect ( docs , :insert ) do
306
- docs
307
- |> Enum . map ( fn
308
- { :ok , % { "n" => n } } -> n
309
- { :ok , _other } -> 0
310
- end )
311
- |> Enum . reduce ( 0 , fn x , acc -> x + acc end )
312
- end
328
+ defp filter_upsert_ids ( nil ) , do: [ ]
329
+ defp filter_upsert_ids ( upserted ) , do: Enum . map ( upserted , fn doc -> doc [ "_id" ] end )
313
330
331
+ ##
332
+ # collects the returns values for each operation
333
+ #
334
+ # the update operation is more complex than insert or delete operation
335
+ #
336
+ defp collect ( { docs , ids } , :insert ) do
337
+
338
+ { docs
339
+ |> Enum . map ( fn
340
+ { :ok , % { "n" => n } } -> n
341
+ { :ok , _other } -> 0
342
+ end )
343
+ |> Enum . reduce ( 0 , fn x , acc -> x + acc end ) , ids }
344
+
345
+ end
314
346
defp collect ( docs , :update ) do
347
+
315
348
docs
316
349
|> Enum . map ( fn
317
- { :ok , % { "n" => n } } -> n
318
- { :ok , _other } -> 0
350
+ { :ok , % { "n" => n , "nModified" => modified , "upserted" => ids } } -> l = length ( ids ) ; { n - l , modified , l , filter_upsert_ids ( ids ) }
351
+ { :ok , % { "n" => matched , "nModified" => modified } } -> { matched , modified , 0 , [ ] }
352
+ { :ok , _other } -> { 0 , 0 , 0 , [ ] }
353
+ end )
354
+ |> Enum . reduce ( { 0 , 0 , 0 , [ ] } , fn
355
+ { mat , mod , ups , ids } , { s_mat , s_mod , s_ups , all } -> { s_mat + mat , s_mod + mod , s_ups + ups , all ++ ids }
319
356
end )
320
- |> Enum . reduce ( 0 , fn x , acc -> x + acc end )
321
- end
322
357
358
+ end
323
359
defp collect ( docs , :delete ) do
360
+
324
361
docs
325
362
|> Enum . map ( fn
326
363
{ :ok , % { "n" => n } } -> n
327
364
{ :ok , _other } -> 0
328
365
end )
329
366
|> Enum . reduce ( 0 , fn x , acc -> x + acc end )
367
+
330
368
end
331
369
370
+ defp run_commands ( conn , { cmds , ids } , opts ) do
371
+ { Enum . map ( cmds , fn cmd -> Mongo . direct_command ( conn , cmd , opts ) end ) , ids }
372
+ end
332
373
defp run_commands ( conn , cmds , opts ) do
333
-
334
- # IO.puts "Running cmds #{inspect cmds}"
335
-
336
- cmds
337
- |> Enum . map ( fn cmd -> Mongo . direct_command ( conn , cmd , opts ) end )
338
- |> Enum . map ( fn { :ok , doc } -> { :ok , doc } end )
374
+ Enum . map ( cmds , fn cmd -> Mongo . direct_command ( conn , cmd , opts ) end )
339
375
end
340
376
341
377
defp get_insert_cmds ( coll , docs , write_concern , _opts ) do
342
378
343
- { _ids , docs } = assign_ids ( docs )
379
+ { ids , docs } = assign_ids ( docs )
344
380
345
- docs
346
- |> Enum . chunk_every ( @ max_batch_size )
347
- |> Enum . map ( fn inserts -> get_insert_cmd ( coll , inserts , write_concern ) end )
381
+ cmds = docs
382
+ |> Enum . chunk_every ( @ max_batch_size )
383
+ |> Enum . map ( fn inserts -> get_insert_cmd ( coll , inserts , write_concern ) end )
384
+ { cmds , ids }
348
385
349
386
end
350
387
351
388
defp get_insert_cmd ( coll , inserts , write_concern ) do
389
+
352
390
[ insert: coll ,
353
391
documents: inserts ,
354
392
writeConcern: write_concern ] |> filter_nils ( )
393
+
355
394
end
356
395
357
396
defp get_delete_cmds ( coll , docs , write_concern , opts ) do
@@ -363,15 +402,20 @@ defmodule Mongo.BulkWrite do
363
402
end
364
403
365
404
defp get_delete_cmd ( coll , deletes , write_concern , opts ) do
405
+
366
406
[ delete: coll ,
367
407
deletes: Enum . map ( deletes , fn delete -> get_delete_doc ( delete ) end ) ,
368
408
ordered: Keyword . get ( opts , :ordered ) ,
369
409
writeConcern: write_concern ] |> filter_nils ( )
410
+
370
411
end
412
+
371
413
defp get_delete_doc ( { filter , opts } ) do
414
+
372
415
[ q: filter ,
373
416
limit: Keyword . get ( opts , :limit ) ,
374
417
collation: Keyword . get ( opts , :collaction ) ] |> filter_nils ( )
418
+
375
419
end
376
420
377
421
defp get_update_cmds ( coll , docs , write_concern , opts ) do
@@ -383,25 +427,27 @@ defmodule Mongo.BulkWrite do
383
427
end
384
428
385
429
defp get_update_cmd ( coll , updates , write_concern , opts ) do
430
+
386
431
[ update: coll ,
387
432
updates: Enum . map ( updates , fn update -> get_update_doc ( update ) end ) ,
388
433
ordered: Keyword . get ( opts , :ordered ) ,
389
434
writeConcern: write_concern ,
390
435
bypassDocumentValidation: Keyword . get ( opts , :bypass_document_validation )
391
436
] |> filter_nils ( )
437
+
392
438
end
393
439
394
440
defp get_update_doc ( { filter , update , update_opts } ) do
441
+
395
442
[ q: filter ,
396
443
u: update ,
397
444
upsert: Keyword . get ( update_opts , :upsert ) ,
398
445
multi: Keyword . get ( update_opts , :multi ) || false ,
399
446
collation: Keyword . get ( update_opts , :collation ) ,
400
447
arrayFilters: Keyword . get ( update_opts , :filters )
401
448
] |> filter_nils ( )
449
+
402
450
end
403
- defp get_update_doc ( _other ) do
404
- [ ]
405
- end
451
+
406
452
407
453
end
0 commit comments