【发布时间】:2017-09-21 13:27:44
【问题描述】:
如何包含类别(“父”)和子类别(“子”)以摆脱 N+1 查询
class Category < ApplicationRecord
belongs_to :parent, class_name: 'Category', foreign_key: :parent_id
has_many :children, class_name: 'Category', foreign_key: :parent_id
has_many :article_categories
has_many :articles, through: :article_categories
scope :roots, -> { where(parent_id: 0) }
scope :children, -> { where.not(parent_id: 0) }
end
parent_id 为 0 的类别是“Category/Parent”
parent_id != 0 的类别是“子类别/儿童”
我在控制器中声明实例:
@articles = articles.includes(:categories)
在视图中:
@articles.each do |article|
article.categories.roots #N+1 query solved using "includes(:categories)"
article.categories.children.first #N+1 query need to solve
..............
问题是因为article.categories.children.first,每一个新的循环都会对数据库产生一个新的请求
N+1 个请求是:
Category Load (0.8ms) SELECT "categories".* FROM "categories" INNER JOIN "article_categories" ON "categories"."id" = "article_categories"."category_id" WHERE "article_categories"."article_id" = $1 AND ("categories"."parent_id" != $2) ORDER BY "categories"."id" ASC LIMIT $3 [["article_id", 450], ["parent_id", 0], ["LIMIT", 1]]
我需要包含“父/类别”
还包括“children/Subcategories”以摆脱来自 ...“children.first”的 N+1 查询
更多细节:
articles.includes(:categories) =>
Article Load (3.9ms) SELECT "articles".* FROM "articles" WHERE "articles"."customer_type" = $1 AND "articles"."aasm_state" IN ('published', 'unpublished') ORDER BY "articles"."title" ASC [["customer_type", 0]]
ArticleCategory Load (3.6ms) SELECT "article_categories".* FROM "article_categories" WHERE "article_categories"."article_id" IN (1, 2, ...)
Category Load (0.7ms) SELECT "categories".* FROM "categories" WHERE "categories"."id" IN (1, 15, ...)
【问题讨论】:
标签: sql ruby-on-rails postgresql activerecord