123456789_123456789_123456789_123456789_123456789_

Class: Mongoid::Association::EagerLoad::LookupPipeline Private

Relationships & Source Files
Inherits: Object
Defined in: lib/mongoid/association/eager_load/lookup_pipeline.rb

Overview

Builds the aggregation pipeline that eager-loads a criteria's inclusions with $lookup.

It starts with the criteria's own match/sort/skip/limit, then lets each root of the inclusion tree contribute its stages. This object owns the stage-building helpers; how each inclusion contributes is the inclusion's own business (see Inclusion).

For Band.eager_load(albums: :tracks) the result is roughly:

[ <criteria match / sort / skip / limit>,
{ '$lookup' => {                 # JoinedInclusion(:albums)
  'from' => 'albums',
  'localField' => '_id',
  'foreignField' => 'band_id',
  'as' => 'albums',
  'pipeline' => [
    { '$sort' => {
      '_id' => 1
    } },
    { '$lookup' => {             # JoinedInclusion(:tracks), nested
      'as' => 'tracks',
      'pipeline' => [
        { '$sort' => {
          '_id' => 1
        } }
      ]
    } }
  ]
} } ]

Class Method Summary

Instance Method Summary

Constructor Details

.new(criteria) ⇒ LookupPipeline

[ GitHub ]

  
# File 'lib/mongoid/association/eager_load/lookup_pipeline.rb', line 42

def initialize(criteria)
  @criteria = criteria
end

Instance Method Details

#discriminator_match(association) (private)

[ GitHub ]

  
# File 'lib/mongoid/association/eager_load/lookup_pipeline.rb', line 100

def discriminator_match(association)
  target = association.klass
  { '$match' => {
    target.discriminator_key => { '$in' => target._types }
  } }
end

#distribute(association, chain, lookup_stage) ⇒ Array<Hash>

Builds the stages that distribute a referenced inclusion living inside an embedded document onto that document.

Parameters:

Returns:

[ GitHub ]

  
# File 'lib/mongoid/association/eager_load/lookup_pipeline.rb', line 83

def distribute(association, chain, lookup_stage)
  EmbeddedDistributor.for(association: association, chain: chain, lookup_stage: lookup_stage).stages
end

#lookup_fields(association) (private)

When the association stores the foreign key on the current document (belongs_to, has_and_belongs_to_many) the local field is that key; for the others (has_many, has_one) the key is on the related document.

[ GitHub ]

  
# File 'lib/mongoid/association/eager_load/lookup_pipeline.rb', line 92

def lookup_fields(association)
  if association.stores_foreign_key?
    [ association.foreign_key, association.primary_key ]
  else
    [ association.primary_key, association.foreign_key ]
  end
end

#lookup_stage_for(association) ⇒ Hash

The $lookup stage for a referenced inclusion: its key fields, a discriminator match when the target shares its collection with sibling subclasses, and an order. Children are added by the inclusion itself.

Parameters:

Returns:

  • (Hash)

    The $lookup stage.

[ GitHub ]

  
# File 'lib/mongoid/association/eager_load/lookup_pipeline.rb', line 61

def lookup_stage_for(association)
  local_field, foreign_field = lookup_fields(association)
  sub_pipeline = []
  sub_pipeline << discriminator_match(association) if association.klass.hereditary?
  sub_pipeline << order(association)
  { '$lookup' => {
    'from' => association.klass.collection.name,
    'localField' => local_field,
    'foreignField' => foreign_field,
    'as' => association.name.to_s,
    'pipeline' => sub_pipeline
  } }
end

#order(association) (private)

[ GitHub ]

  
# File 'lib/mongoid/association/eager_load/lookup_pipeline.rb', line 107

def order(association)
  unless association.order
    return { '$sort' => {
      '_id' => 1
    } }
  end

  ordering = association.order
  ordering = { ordering => 1 } unless ordering.is_a?(Hash)
  { '$sort' => ordering }
end

#stagesArray<Hash>

Returns:

  • (Array<Hash>)

    The aggregation pipeline stages.

[ GitHub ]

  
# File 'lib/mongoid/association/eager_load/lookup_pipeline.rb', line 47

def stages
  pipeline = @criteria.selector.to_pipeline
  pipeline.concat(@criteria.options.to_pipeline_for_lookup)
  InclusionTree.from(@criteria.inclusions, self).contribute_to(pipeline)
  pipeline
end