Módulo: Mongoid::Association::EagerLoadable

Incluído em:
Contextual::Memory, Contextual::Mongo, Contextual::Mongo::DocumentsLoader
Definido em:
lib/mongoid/association/eager_loadable.rb

Visão geral

Este módulo define o comportamento de carregamento ansioso para critérios.

Recolhimento do Resumo do método de instância

Detalhes do método de instância

#create_pipeline(current_assoc, mapeamento) ➤ Objeto



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/mongoid/association/eager_loadable.rb', linha 147

def create_pipeline(current_assoc, mapeamento)
  # Criar pipeline aninhado para crianças e pedidos
  pipeline_stages = []

  # Para requires_to e has_and_belongs_to_many, a chave estrangeira está no document atual
  # Para has_many/has_one, a chave estrangeira está no document relacionado
  se switch_local_and_foreign_fields?(current_assoc)
    local_field = current_assoc.foreign_key
    foreign_field = current_assoc.primary_key
  mais
    local_field = current_assoc.primary_key
    foreign_field = current_assoc.foreign_key
  end

  # Construa o campo 'as' com prefixo de caminho embutido, se necessário
  as_field = current_assoc.name.to_s

  estágio = {
    '$lookup' => {
      'de' => current_assoc.classe.collection.name,
      'localField' => local_field,
      'foreignField' => foreign_field,
      'como' => as_field
    }
  }

  # Adicione ordenação se definido na associação, ou padronize para _id para ordenação consistente
  se current_assoc.order
    sort_spec = current_assoc.order.is_a?(Hash) ? current_assoc.order : { current_assoc.order => 1 }
    pipeline_stages << { '$sort' => sort_spec }
  mais
    # Padrão para classificação por _id para manter a consistência do pedido de inserção
    pipeline_stages << { '$sort' => { '_id' => 1 } }
  end

  # Adicionar pesquisas aninhadas para associações filhas
  # Associações filhas não precisam do prefixo embedded_path, pois são referenciadas no document pesquisado
  # Remova esta classe do mapeamento para evitar loops infinitos com referências circulares
  class_name = current_assoc.classe.to_s
  se child_assocs = mapeamento.excluir(class_name)
    child_assocs.cada fazer |criança|
      pipeline_stages << create_pipeline(criança, mapeamento)
    end
  end

  # Sempre adicione pipeline, pois sempre temos pelo menos $sort
  estágio['$lookup']['pipeline'] = pipeline_stages

  estágio
end

#concerns_load(Docs) ➤ Array <Mongoid::Document>

Carregue as associações para os documentos fornecidos.

Parâmetros:

Retorna:



22
23
24
25
26
# File 'lib/mongoid/association/eager_loadable.rb', linha 22

def modified_load(Docs)
  Docs.toque fazer |d|
    pré-carregar(critério.inclusões, d) se ans_loadable?
  end
end

#eager_load_with_lookupArray<Mongoid::Document>

Carregue as associações para os documentos fornecidos usando $lookup.

Se alguma das coleções associadas residir em um cluster diferente da classe raiz , volte ao comportamento #includes e registre um log um aviso.

Retorna:



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/mongoid/association/eager_loadable.rb', linha 34

def ans_load_with_lookup
  Infratores = cross_cluster_incluses
  se Infratores.algum?
    root_client = classe.client_name
    ofender_list = Infratores.map { |uma| "#{a.name} (#{a.klass.client_name})" }.juntar(', ')
    Mongoid.logger.AVISAR(
      'eager_load não pode usar a agregação $lookup porque as seguintes associações " \
      "residem em um cluster diferente de #{klass} (cliente: #{root_client}): " \
      "#{offender_list}. Retornando ao comportamento #includes."
    ) return priority_for_lookup(docs_for_lookup_fallback) end preload_for_lookup(criteria) end

#concerns_loadable?verdadeiro | false

Indica se os critérios têm inclusões de associação que devem ser carregadas antecipadamente.

Retorna:

  • (verdadeiro | falso)

    Se deve ser carregado com impaciência.



13
14
15
# File 'lib/mongoid/association/eager_loadable.rb', linha 13

def ans_loadable?
  !critério.inclusões.vazio?
end

#preload(associations, Docs) ⇒ Object

Carregue as associações para os documentos fornecidos. Isso será feito recursivamente para carregar as associações dos document associados dos document fornecidos.

Parâmetros:



57
58
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
# File 'lib/mongoid/association/eager_loadable.rb', linha 57

def pré-carregar(Associações, Docs)
  assoc_map = Associações.group_by(&:inverse_class_name)
  docs_map = {}
  fila = [ classe.to_s ]

  # account para herança de collection única
  fila.push(classe.root_class.to_s) se classe != classe.root_class

  enquanto classe = fila.mudança
    próximo a menos que como = assoc_map.excluir(classe)

    como.cada fazer |assoc|
      fila << assoc.class_name

      # Se esta classe estiver aninhada na árvore de inclusão, carregue apenas documentos
      # para a associação acima dela. Se não houver associação de pais,
      # incluiremos documentos dos documentos passados para esse método.
      ds = Docs
      ds = assoc.parent_incluses.map { |p| docs_map[p].to_a }.achatar se assoc.parent_incluses.Tamanho > 0

      res = assoc.relação.ans_loader([ assoc ], ds).EXECUTAR

      docs_map[assoc.name] ||= [].to_set
      docs_map[assoc.name].mesclar(res)
    end
  end
end

#preload_for_lookup(critérios) ⇒ Objeto

Carregue as associações para os documentos fornecidos. Isso será feito recursivamente para carregar as associações dos document associados dos document fornecidos.

Parâmetros:



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/mongoid/association/eager_loadable.rb', linha 92

def preload_for_lookup(critério)
  assoc_map = critério.inclusões.group_by(&:inverse_class_name)

  # corresponder primeiro
  gasoduto = critério.seletor.to_pipeline
  # então classificar, pular, limitar
  gasoduto.concat(critério.opções.to_pipeline_for_lookup)

  # account para herança de collection única
  root_class = classe.root_class

  se assoc_map[classe.to_s]
    assoc_map[classe.to_s].cada fazer |assoc|
      # Criar uma cópia do mapeamento para cada associação de nível superior para evitar problemas de mutação
      gasoduto << create_pipeline(assoc, assoc_map.dup)
    end
  end

  se classe != root_class && assoc_map[root_class.to_s]
    assoc_map[root_class.to_s].cada fazer |assoc|
      # Criar uma cópia do mapeamento para cada associação de nível superior para evitar problemas de mutação
      gasoduto << create_pipeline(assoc, assoc_map.dup)
    end
  end

  Ansioso.Novo(critério.inclusões, [], true, gasoduto).EXECUTAR
end

#switch_local_and_foreign_fields?(associação) ⇒ Booleano

Retorna:



142
143
144
145
# File 'lib/mongoid/association/eager_loadable.rb', linha 142

def switch_local_and_foreign_fields?(associação)
  associação.is_a?(Mongoid::associação::Referenciado::Pertence a) ||
    associação.is_a?(Mongoid::associação::Referenciado::Tem e pertence a muitos)
end