`map`执行N + 1个查询

时间:2015-09-09 12:13:46

标签: ruby-on-rails ruby

在我的代码中,我有一个选项包括:

nodes_list =
  Foo
  .where(id: foo_ids)
  .includes(node: [:nodes, node_image, :parent_node])
  .includes(:bar, :foo_image)
  .flat_map {|foo| [foo.node, foo.node.parent_node]}.uniq.compact

此部分工作正常,可以按预期避免N + 1个查询。但是,稍后在我的代码中,我有这个:

nodes_list.map do |node|
  if node.nodes.empty?
    image = node.foo.foo_image
  else
    image = node.node_image
  end

  {
    id: node.id,
    name: node.name,
    image: image,
    parent_id: node.parent_node,
  }
end

在这种情况下,我在parent_nodenodesnode_image上有N + 1个查询,这些查询应该在我的includes中。如何避免那些N + 1查询?

1 个答案:

答案 0 :(得分:3)

我认为您看到这些N + 1查询的原因是您没有在parent_node中包含任何内容我认为如果您这样写它可以避免:

nodes_list =
  Foo
  .where(id: foo_ids)
  .includes(node: [:nodes, :node_image, parent_node: [:nodes, :node_image, :parent_node]])
  .includes(:bar, :foo_image)
  .flat_map {|foo| [foo.node, foo.node.parent_node]}.uniq.compact

完全独立于我想添加以下内容的问题:

您可以删除includes(:bar, :foo_image),因为这只会导致额外的工作。您使用foosbar获取和装饰的foo_image将被丢弃,而不使用这些预取的装饰。