Class: Mongoid::Association::EagerLoad::EmbeddedDistributor Private

Inherits:
Object
  • Object
show all
Defined in:
lib/mongoid/association/eager_load/embedded_distributor.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Distributes the results of a $lookup onto the embedded documents they belong to.

A $lookup overwrites the single field it writes to, and it can't distribute its matches across the elements of an embedded array. So when the reference being eager-loaded lives on an embedded document, the matches are first collected in a temporary top-level field and then distributed down the embedded path onto each embedded document, merging into it (so the rest of the document is kept) and correlating by key. The temporary field is then dropped.

For Computer.eager_load(port: :device) (Port belongs_to :device) it emits:

{ '$lookup' => {                     # devices can't be written into
'from' => 'devices',               # the embedded port, so they are
'localField' => 'port.device_id',  # collected in a temp top-level
'foreignField' => '_id',           # field instead
'as' => '__eager_load_port_device'
} },
{ '$set' => {
'port' => { '$mergeObjects' => [   # merge a 'device' key onto the port
  '$port',
  { 'device' => { '$filter' => { ... } } }   # this port's matches
] }
} },
{ '$unset' => '__eager_load_port_device' }  # drop the temp field

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(association, chain, lookup_stage, local_field, foreign_field) ⇒ EmbeddedDistributor

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of EmbeddedDistributor.



53
54
55
56
57
58
59
# File 'lib/mongoid/association/eager_load/embedded_distributor.rb', line 53

def initialize(association, chain, lookup_stage, local_field, foreign_field)
  @association = association
  @chain = chain
  @lookup_stage = lookup_stage
  @local_field = local_field
  @foreign_field = foreign_field
end

Class Method Details

.for(association:, chain:, lookup_stage:) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



45
46
47
48
# File 'lib/mongoid/association/eager_load/embedded_distributor.rb', line 45

def for(association:, chain:, lookup_stage:)
  lookup = lookup_stage['$lookup']
  new(association, chain, lookup_stage, lookup['localField'], lookup['foreignField'])
end

Instance Method Details

#stagesArray<Hash>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The stages that run the $lookup into a temporary field and then distribute its matches onto the embedded documents along the path.

Returns:

  • (Array<Hash>)

    The stages to append to the pipeline.



65
66
67
68
69
70
71
72
73
74
# File 'lib/mongoid/association/eager_load/embedded_distributor.rb', line 65

def stages
  redirect_lookup_to_temporary_field
  [
    @lookup_stage,
    { '$set' => {
      root => distributed_value(@chain, "$#{root}")
    } },
    { '$unset' => temporary_field }
  ]
end