簡體   English   中英

Rails ActiveAdmin 消除對屬於另一個模型的自定義屬性的 n+1 查詢

[英]Rails ActiveAdmin Eliminating n+1 queries on custom attributes belong to another model

我正在使用 activeadmin 來顯示分支模型記錄,分支模型有很多分支電話,我想在 activeadmin 分支模型屏幕上顯示為此分支創建的第一個分支電話作為額外的自定義屬性,所以我是這樣寫的

    show do
    attributes_table do
      row :id
      row :manager_name
      row :manager_email
      row :phone_number do |branch|
        branch&.branch_phones&.order(created_at: :asc)&.first&.phone_number
      end
    end
  end

  index do
    column :id
    column :manager_name
    column :manager_email
    column :phone_number do |branch|
      branch&.branch_phones&.order(created_at: :asc)&.first&.phone_number
    end
    actions
  end

該代碼的問題在於它導致我 n+1 次查詢,每次代碼獲得一個分支時,它都會在其中創建一個額外的查詢以獲取分支的分支電話,這會在調用分支模型時產生類似的結果activeadmin 上的屏幕

Processing by Admin::BranchesController#index as HTML
  Parameters: {"subdomain"=>""}
  AdminUser Load (0.8ms)  SELECT  "admin_users".* FROM "admin_users" WHERE "admin_users"."id" = $1 ORDER BY "admin_users"."id" ASC LIMIT $2  [["id", 1], ["LIMIT", 1]]
  Rendering /usr/local/bundle/gems/activeadmin-2.7.0views/active_admin/resource/index.html.arb
   (0.6ms)  SELECT COUNT(*) FROM (SELECT  1 AS one FROM "branches" LIMIT $1 OFFSET $2) subquery_for_count  [["LIMIT", 30], ["OFFSET", 0]]
  CACHE  (0.1ms)  SELECT COUNT(*) FROM (SELECT  1 AS one FROM "branches" LIMIT $1 OFFSET $2) subquery_for_count  [["LIMIT", 30], ["OFFSET", 0]]
   (0.4ms)  SELECT COUNT(*) FROM "branches"
  CACHE  (0.0ms)  SELECT COUNT(*) FROM (SELECT  1 AS one FROM "branches" LIMIT $1 OFFSET $2) subquery_for_count  [["LIMIT", 30], ["OFFSET", 0]]
  Branch Load (0.5ms)  SELECT  "branches".* FROM "branches" ORDER BY "branches"."id" desc LIMIT $1 OFFSET $2  [["LIMIT", 30], ["OFFSET", 0]]
  Store Load (0.6ms)  SELECT "stores".* FROM "stores" WHERE "stores"."id" IN ($1, $2, $3)  [["id", 21], ["id", 1], ["id", 2]]
  BranchPhone Load (0.4ms)  SELECT "branch_phones".* FROM "branch_phones" WHERE "branch_phones"."branch_id" IN ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)  [["branch_id", 25], ["branch_id", 24], ["branch_id", 22], ["branch_id", 20], ["branch_id", 19], ["branch_id", 14], ["branch_id", 11], ["branch_id", 4], ["branch_id", 3], ["branch_id", 2], ["branch_id", 1]]
  BranchPhone Load (0.7ms)  SELECT  "branch_phones".* FROM "branch_phones" WHERE "branch_phones"."branch_id" = $1 ORDER BY "branch_phones"."created_at" ASC LIMIT $2  [["branch_id", 25], ["LIMIT", 1]]
  BranchPhone Load (0.5ms)  SELECT  "branch_phones".* FROM "branch_phones" WHERE "branch_phones"."branch_id" = $1 ORDER BY "branch_phones"."created_at" ASC LIMIT $2  [["branch_id", 24], ["LIMIT", 1]]
  BranchPhone Load (0.3ms)  SELECT  "branch_phones".* FROM "branch_phones" WHERE "branch_phones"."branch_id" = $1 ORDER BY "branch_phones"."created_at" ASC LIMIT $2  [["branch_id", 22], ["LIMIT", 1]]
  BranchPhone Load (0.6ms)  SELECT  "branch_phones".* FROM "branch_phones" WHERE "branch_phones"."branch_id" = $1 ORDER BY "branch_phones"."created_at" ASC LIMIT $2  [["branch_id", 20], ["LIMIT", 1]]
  BranchPhone Load (0.3ms)  SELECT  "branch_phones".* FROM "branch_phones" WHERE "branch_phones"."branch_id" = $1 ORDER BY "branch_phones"."created_at" ASC LIMIT $2  [["branch_id", 19], ["LIMIT", 1]]
  BranchPhone Load (0.3ms)  SELECT  "branch_phones".* FROM "branch_phones" WHERE "branch_phones"."branch_id" = $1 ORDER BY "branch_phones"."created_at" ASC LIMIT $2  [["branch_id", 14], ["LIMIT", 1]]
  BranchPhone Load (0.2ms)  SELECT  "branch_phones".* FROM "branch_phones" WHERE "branch_phones"."branch_id" = $1 ORDER BY "branch_phones"."created_at" ASC LIMIT $2  [["branch_id", 11], ["LIMIT", 1]]
  BranchPhone Load (0.2ms)  SELECT  "branch_phones".* FROM "branch_phones" WHERE "branch_phones"."branch_id" = $1 ORDER BY "branch_phones"."created_at" ASC LIMIT $2  [["branch_id", 4], ["LIMIT", 1]]
  BranchPhone Load (0.3ms)  SELECT  "branch_phones".* FROM "branch_phones" WHERE "branch_phones"."branch_id" = $1 ORDER BY "branch_phones"."created_at" ASC LIMIT $2  [["branch_id", 3], ["LIMIT", 1]]
  BranchPhone Load (0.2ms)  SELECT  "branch_phones".* FROM "branch_phones" WHERE "branch_phones"."branch_id" = $1 ORDER BY "branch_phones"."created_at" ASC LIMIT $2  [["branch_id", 2], ["LIMIT", 1]]
  BranchPhone Load (0.2ms)  SELECT  "branch_phones".* FROM "branch_phones" WHERE "branch_phones"."branch_id" = $1 ORDER BY "branch_phones"."created_at" ASC LIMIT $2  [["branch_id", 1], ["LIMIT", 1]]
  Rendered /usr/local/bundle/gems/activeadmin-2.7.0views/active_admin/resource/index.html.arb (219.4ms)
Completed 200 OK in 258ms (Views: 208.7ms | ActiveRecord: 23.2ms)

那么,有什么解決方案可以消除分支電話的 n+1 查詢? 知道我試圖使用這樣的控制器操作來消除它在此處輸入圖片說明

但仍然沒有解決分支電話 N+1 查詢

在此處輸入圖片說明

您正在收到 (N+1) 查詢,因為您正在訂購branch_phones 默認情況下,Rails 按同意順序返回記錄。 您不必再次訂購。

我相信你有一些像下面這樣的關聯:

# app/models/branch.rb

class Branch < ApplicationRecord
  has_many :branch_phones
end
# app/models/branch_phone.rb

class BranchPhone < ApplicationRecord
  belongs_to :branch
end

請將此行添加到您的app/admin/brach.rb文件中。

# app/admin/brach.rb

controller do
  def scoped_collection
    super.includes(:branch_phones)
  end
end

index do
  column :id
  column :manager_name
  column :manager_email
  column :phone_number do |branch|
    branch.branch_phones.first&.phone_number
  end

  actions
end

現在include方法在 ActiveAdmin 中可用。 您需要做的就是將其添加到所需的管理文件中。

# app/admin/brach.rb
ActiveAdmin.register Branch do

  includes :branch_phones

  index do
    column :id
    column :manager_name
    column :manager_email
    column :phone_number do |branch|
      branch&.branch_phones&.order(created_at: :asc)&.first&.phone_number
    end
    actions
  end
end

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM