模块:Mongoid::Association::EagerLoadable

包含在:
Contextual::MemoryContextual::MongoContextual::Mongo::DocumentsLoader
定义于:
lib/mongoid/association/eager_loadable.rb

Overview

此模块定义条件的预先加载行为。

实例方法摘要折叠

实例方法详细信息

#create_pipeline(current_assoc, mapping) ⇒ 对象



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', line 147

def create_pipeline(current_assoc, 映射)
  # 为子项和排序构建嵌套管道
  pipeline_stages = []

  # 对于 belongs_to 和 has_and_belongs_to_many,外键位于当前 document
  # 对于 has_many/has_one,外键位于相关 document 上
  if switch_local_and_foreign_fields?(current_assoc)
    local_field = current_assoc.foreign_key
    foreign_field = current_assoc.primary_key
  else
    local_field = current_assoc.primary_key
    foreign_field = current_assoc.foreign_key
  end

  # 如果需要,构建带有嵌入式路径前缀的 'as'字段
  as_field = current_assoc.名称.to_s

  阶段 = {
    ' $lookup ' => {
      ' from ' => current_assoc.klass.集合.名称,
      'localField' => local_field,
      'foreignField' => foreign_field,
      'as' => as_field
    }
  }

  # 如果在关联上定义了排序,则添加排序,或者默认为_id以获得一致的顺序
  if current_assoc.来自一个购物车应用的order文档,
    sort_spec = current_assoc.来自一个购物车应用的order文档,.is_a?(哈希) ? current_assoc.来自一个购物车应用的order文档, : { current_assoc.来自一个购物车应用的order文档, => 1 }
    pipeline_stages << { '$sort' => sort_spec }
  else
    # 默认按_id排序,以保持插入顺序的一致性
    pipeline_stages << { '$sort' => { '_id' => 1 } }
  end

  # 为子关联添加嵌套查找
  # 子关联不需要 embedded_path 前缀,因为它们是从查找到的 document 中引用的
  # 从映射中删除此类,以防止循环引用带来的无限循环
  class_name = current_assoc.klass.to_s
  if child_assocs = 映射.删除(class_name)
    child_assocs. do |子项|
      pipeline_stages << create_pipeline(子项, 映射)
    end
  end

  # 始终添加管道,因为我们始终至少有 $sort
  阶段[' $lookup ']['管道'] = pipeline_stages

  阶段
end

#ager_load ( Docs ) ⇒ Array< Mongoid::Document >

加载给定文档的关联。

参数:

返回:



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

def ager_load(docs)
  docs.点击 do |d|
    预加载(条件.包含, d) if ager_loadable?
  end
end

#eager_load_with_lookup数组<Mongoid::Document>

使用 $lookup 加载给定 document 的关联。

如果任何关联的集合与根类位于不同的集群,则回退到 #includes 行为并记录警告。

返回:



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

def Eager_load_with_lookup
  Offenders = cross_cluster_inclusions
  if Offenders.任何?
    root_client = klass.client_name
    Offender_list = Offenders.map { |a| "#{a.name} (#{a.klass.client_name})" }.连接 (JOIN)(' , ')
    Mongoid.记录器.WARN(
      'agers_load 无法使用 $lookup聚合,因为以下关联 ' \
      \"#{klass} 位于不同的集群(客户端:#{root_client}):\" \
      \"#{offender_list}。 #includes 行为。\") returnagerd_load(docs_for_lookup_fallback)end preload_for_lookup(criteria)end

#ager_loadable?true | false

指示条件是否包含应预先加载的关联包含项。

返回:

  • ( true | false )

    是否预先加载。



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

def ager_loadable?
  !条件.包含.空?
end

# preload (associations, Docs ) ⇒对象

加载给定 document 的关联。这将以递归方式完成,以加载给定文档的关联文档的关联。

参数:



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', line 57

def 预加载(关联, docs)
  assoc_map = 关联.GROUP_BY(:inverse_class_name)
  docs_map = {}
  队列 = [ klass.to_s ]

  # 考虑单集合继承
  队列.推动(klass.root_class.to_s) if klass != klass.root_class

  while klass = 队列.转变
    来年 除非 作为 = assoc_map.删除(klass)

    作为. do |assoc|
      队列 << assoc.class_name

      # 如果此类嵌套在包含树中,则仅加载文档
      # 用于其上方的关联。 如果没有父关联,
      # 我们将包含传递给此方法的文档中的文档。
      ds = docs
      ds = assoc.parent_inclusions.map { |p| docs_map[p].to_a }.展平 if assoc.parent_inclusions.长度 > 0

      res = assoc.关系.Eager_Loader([ assoc ], ds).运行

      docs_map[assoc.名称] ||= [].to_set
      docs_map[assoc.名称].合并(merge)(res)
    end
  end
end

# preload_for_lookup (criteria) ⇒ 对象

加载给定 document 的关联。这将以递归方式完成,以加载给定文档的关联文档的关联。

参数:



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', line 92

def preload_for_lookup(条件)
  assoc_map = 条件.包含.GROUP_BY(:inverse_class_name)

  # 首先匹配
  管道 = 条件.选择器.to_pipeline
  # then sort、skip、limit
  管道.concat(条件.选项.to_pipeline_for_lookup)

  # 考虑单集合继承
  root_class = klass.root_class

  if assoc_map[klass.to_s]
    assoc_map[klass.to_s]. do |assoc|
      # 为每个顶级关联创建映射副本,以避免突变问题
      管道 << create_pipeline(assoc, assoc_map.dup)
    end
  end

  if klass != root_class && assoc_map[root_class.to_s]
    assoc_map[root_class.to_s]. do |assoc|
      # 为每个顶级关联创建映射副本,以避免突变问题
      管道 << create_pipeline(assoc, assoc_map.dup)
    end
  end

  Eager.new(条件.包含, [], true, 管道).运行
end

# switch_local_and_foreign_fields?(关联)→ 布尔值

返回:



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

def switch_local_and_foreign_fields?(关联)
  关联.is_a?(Mongoid::关联::引用::属于关联) ||
    关联.is_a?(Mongoid::关联::引用::拥有并且属于许多)
end