Module: Mongoid::Association::Embedded::Batchable

Includes:
Positional
Included in:
EmbedsMany::Proxy
Defined in:
lib/mongoid/association/embedded/batchable.rb

Overview

Contains behavior for executing operations in batch on embedded documents.

Instance Method Summary collapse

Methods included from Positional

#positionally

Instance Method Details

#batch_clear(docs) ⇒ Array

Clear all of the docs out of the association in a single swipe.

Examples:

Clear all docs.

batchable.batch_clear(docs)

Parameters:

  • docs (Array<Document>)

    The docs to clear.

Returns:

  • (Array)

    The empty array.



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/mongoid/association/embedded/batchable.rb', line 35

def batch_clear(docs)
  pre_process_batch_remove(docs, :delete)
  unless docs.empty?
    collection.find(selector).update_one(
      positionally(selector, "$unset" => { path => true }),
      session: _session
    )
    # This solves the case in which a user sets, clears and resets an
    # embedded document. Previously, since the embedded document was
    # already marked not a "new_record", it wouldn't be persisted to
    # the second time. This change fixes that and allows it to be persisted.
    docs.each { |doc| doc.new_record = true }
    post_process_batch_remove(docs, :delete)
  end
  _unscoped.clear
end

#batch_insert(docs) ⇒ Array<Hash>

Insert new documents as a batch push ($push with $each). This ensures that all callbacks are run at the appropriate time and only 1 request is made to the database.

Examples:

Execute the batch push.

batchable.batch_insert([ doc_one, doc_two ])

Parameters:

  • docs (Array<Document>)

    The docs to add.

Returns:

  • (Array<Hash>)

    The inserts.



23
24
25
# File 'lib/mongoid/association/embedded/batchable.rb', line 23

def batch_insert(docs)
  execute_batch_push(docs)
end

#batch_remove(docs, method = :delete) ⇒ Object

Batch remove the provided documents as a $pullAll or $pull.

Examples:

Batch remove the documents.

batchable.batch_remove([ doc_one, doc_two ])

Parameters:

  • docs (Array<Document>)

    The docs to remove.

  • method (Symbol) (defaults to: :delete)

    Delete or destroy.



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/mongoid/association/embedded/batchable.rb', line 59

def batch_remove(docs, method = :delete)
  # If the _id is nil, we cannot use $pull and delete by searching for
  # the id. Therefore we have to use pullAll with the documents'
  # attributes.
  removals = pre_process_batch_remove(docs, method)
  pulls, pull_alls = removals.partition { |o| !o["_id"].nil? }

  if !_base.persisted?
    post_process_batch_remove(docs, method) unless docs.empty?
    return reindex
  end

  if !docs.empty?
    if !pulls.empty?
      collection.find(selector).update_one(
        positionally(selector, "$pull" => { path => { "_id" => { "$in" => pulls.pluck("_id") } } }),
        session: _session
      )
    end
    if !pull_alls.empty?
      collection.find(selector).update_one(
        positionally(selector, "$pullAll" => { path => pull_alls }),
        session: _session
      )
    end
    post_process_batch_remove(docs, method)
  else
    collection.find(selector).update_one(
      positionally(selector, "$set" => { path => [] }),
      session: _session
    )
  end
  reindex
end

#batch_replace(docs) ⇒ Array<Hash>

Batch replace the provided documents as a $set.

Examples:

Batch replace the documents.

batchable.batch_replace([ doc_one, doc_two ])

Parameters:

  • docs (Array<Document> | Array<Hash>)

    The docs to replace with.

Returns:

  • (Array<Hash>)

    The inserts.



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/mongoid/association/embedded/batchable.rb', line 102

def batch_replace(docs)
  if docs.blank?
    if _assigning? && !empty?
      _base.delayed_atomic_sets.delete(path)
      clear_atomic_path_cache
      _base.add_atomic_unset(first)
      target_duplicate = _target.dup
      pre_process_batch_remove(target_duplicate, :delete)
      post_process_batch_remove(target_duplicate, :delete)
    else
      batch_remove(_target.dup)
    end
  elsif _target != docs
    _base.delayed_atomic_sets.delete(path) unless _assigning?
    docs = normalize_docs(docs).compact
    _target.clear and _unscoped.clear
    _base.delayed_atomic_unsets.delete(path)
    clear_atomic_path_cache
    inserts = execute_batch_set(docs)
    add_atomic_sets(inserts)
  end
end