Rails 3.2.13 с PostgreSQLжадная загрузка ассоциации со сложным запросом
Мы пытаемся оптимизировать следующий код модели, который извлекает набор электронной коммерции Заказы из базы данных, на основе заданных пользователем критериев фильтрации.
Пользователь может выбрать, чтобы отфильтровать заказы на основании статуса заказа, статуса оплаты & Статус доставки. Они могут установить для них либо ==
, либо <>
конкретное значение для каждого.
После этого мы отфильтровываем любые цифровые заказы, а затем разбиваем на страницы результаты.
Все это хорошо работает, за исключением того, что у Ордена есть много ассоциаций, таких как продукты, адреса, платежи и т. Д. Это вызывает N + 1 запросы и делает процесс чрезвычайно медленным.
Order.rb:
belongs_to :shop
has_many :shipping_lines , :dependent => :destroy
has_many :line_items , :dependent => :destroy
has_many :taxlines , :dependent => :destroy
has_many :fulfillments , :dependent => :destroy
has_many :notes , :dependent => :destroy
has_many :discounts , :dependent => :destroy
has_one :billing_address , :dependent => :destroy
has_one :shipping_address , :dependent => :destroy
has_one :payment_detail, :dependent => :destroy
has_many :order_histories, :dependent => :destroy
Любых идеи о том, как мы можем включать ассоциации нетерпеливых загруженные в ниже запросе?
Пример ввод: пользователь может хочет видеть любого (открытый или закрытый), оплаченные заказы, которые еще не погружен
Order Status == 'open'
Payment Status == 'any'
Shipping Status <> 'shipped'
Магазин идентифицируются субдомен
def by_filter(subdomain, filter,page)
shop_condition = "shop_id = #{subdomain.shops[0].id}"
if filter.name != "All"
if filter.order_status == "any"
status_condition = "status in (?)"
order_status = Filter::ORDER_STATUS.values - ["any"]
else
status_condition = "status #{Filter::STATUS_OPERATORS_MAPPING[filter.order_status_operator]} ?"
order_status = filter.order_status
end
if filter.payment_status == "any"
payment_status_condition = "payment_status in (?)"
payment_status = Filter::PAYMENT_STATUS.values - ["any"]
else
payment_status_condition = "payment_status #{Filter::STATUS_OPERATORS_MAPPING[filter.payment_status_operator]} ?"
payment_status = filter.payment_status
end
if filter.fulfillment_status == "any"
fulfillment_status_condition = "fulfillment_status in (?)"
fulfillment_status = Filter::FULFILLMENT_STATUS.values - ["any"]
else
fulfillment_status_condition = "fulfillment_status #{Filter::STATUS_OPERATORS_MAPPING[filter.fulfillment_status_operator]} ?"
fulfillment_status = filter.fulfillment_status
end
conditions = "#{status_condition} AND #{payment_status_condition} AND #{fulfillment_status_condition} AND #{shop_condition} "
else
conditions = shop_condition
end
orders = self.where([conditions, order_status, payment_status, fulfillment_status]).order("order_created_at #{filter.sort_by}")
if filter.digital_orders
orders_arr = ((orders.all.collect(&:shipping_address) - [nil]).collect(&:order)).flatten
orders = Kaminari.paginate_array(orders_arr).page(page).per(filter.show)
else
orders = orders.page(page).per(filter.show)
end
return orders
end
СКПА Созданный запрос выглядит так:
SELECT "orders".* FROM "orders" WHERE (status = 'open' AND payment_status in ('authorized', 'pending', 'paid', 'partially_paid', 'partially_refunded', 'refunded', 'voided') AND fulfillment_status <> 'shipped' AND shop_id = 58) ORDER BY order_created_at DESC
Мы попытались сделать регулярное .includes, но t его, кажется, не имеет никакого эффекта. Например:
orders = self.includes(:shipping_address).where([conditions, order_status, payment_status, fulfillment_status]).order("order_created_at #{filter.sort_by}")
Выберите один сайт и удалить другой вопрос пожалуйста. Вы дублировали это здесь: http://codereview.stackexchange.com/q/41650/26613 и даже не потрудились связывать их, поэтому вы, вероятно, будете тратить время людей на дублирующие ответы. –
Извинения, исправлено сейчас. Спасибо, что указали это. –