Есть 2 модели BuyerOrder и BuyerOrder с отношением 1 ко многим.
class Buyer < ApplicationRecord
has_many buyer_orders
end
class BuyerOrder < ApplicationRecord
belongs_to buyer
end
Мне нужно получить общее количество покупателей_заказов и имя покупателя с группой по покупателю_id.
Я могу получить необходимые данные по запросу ниже.
Buyer.all.map{|buyer| {buyer.id => {buyer_name: buyer.name, total: buyer.buyer_orders.count}}}
Результат этого запроса:
[{1=>{:buyer_name=>"Buyer 1", :total=>58}},
{2=>{:buyer_name=>"Buyer 2", :total=>10}},
{3=>{:buyer_name=>"Buyer 3", :total=>4}}]
Но этот запрос имеет проблему N+1. Как можно оптимизировать запрос, чтобы устранить проблему N+1? Моя версия Rails — 6.0.3.2, а версия Mysql — 8.0.33.
Может ли кто-нибудь помочь мне решить мою проблему?
Используйте метод includes
, чтобы загрузить ассоциацию в результат запроса, также используйте size
, вместо count
, size
проверьте, загружена ли ассоциация перед вызовом базы данных.
Buyer.all.includes(:buyer_orders).map{ |buyer| { buyer.id => { buyer_name: buyer.name, total: buyer.buyer_orders.size }}}
Я отредактировал свой ответ, попробуйте использовать size
вместо count
Я думаю, что вы должны использовать BuyerOrder
в качестве отправной точки вместо Buyer
, потому что из BuyerOrder
вы уже можете сгруппировать их по атрибуту buyer_id
.
Следующий запрос отправится 2 раза в базу данных, независимо от того, сколько у вас Buyers
или BuyerOrders
:
BuyerOrder.group(:buyer).count.map { |buyer| { buyer[0].id => { buyer_name: buyer[0].buyer_name, total: buyer[1]} } }
Это даст желаемый результат без проблемы N+1.
Спасибо за Ваш ответ. запрос count все еще выполняется несколько раз.