【发布时间】:2014-01-20 18:41:47
【问题描述】:
我有一个处理带有订单项的订单的应用程序。订单项以 JSON 格式作为订单的一部分出现,例如:
{
"customer_id":24,
"line_items":[
{
"variant_id":"1423_101_10",
"quantity":"5",
"product_id":"1423"
},
{
"variant_id":"2396_101_12",
"quantity":"3",
"product_id":"2396"
}
]
}
所以这将在订单表中设置一个订单,例如:
id | customer_id
1 | 24
以及 line_items 表中的订单项,例如:
id | order_id | product_id | variant_id | quantity | price*
1 | 1 | 1423 | 1423_101_10 | 5 | 10
2 | 1 | 2396 | 2396_101_10 | 3 | 15
*price 不是来自订单 JSON,而是通过查找检索到的
但是,当创建新记录时,它会为添加的每个 line_item 的订单执行 SELECT。在上面的示例中这不是问题,但是这个应用程序可以并且确实有数百甚至数千个特定订单的订单项,因此它看起来效率低下并且可能是 Heroku 服务器内存不足的原因。有没有办法只加载一次订单,而不是每个订单项?
另一个潜在的瓶颈是针对 Products 表进行查找以获取价格。在上面的示例中,没有可能的缓存,但如果选择了同一产品的多个变体,则每次可能已经加载的产品时查找它似乎效率低下。例如,1423_101_10、1423_101_12、1423_102_10 和 1423_102_12 都是相同价格的相同产品。尝试缓存已经查找过的产品会更好,还是会使事情进一步复杂化?
编辑:
完全忘记添加任何代码!
订购型号:
class Order < ActiveRecord::Base
has_many :line_items, :dependent => :destroy
订单项模型:
class LineItem < ActiveRecord::Base
before_create :set_price
belongs_to :order
belongs_to :product, :primary_key => "product_id", :conditions => proc { "season = '#{order.season}'" }
def set_price
write_attribute :price, product.prices[order.currency] if price.nil? && product && order
end
产品型号:
class Product < ActiveRecord::Base
编辑 2:
OrdersController(简化版)
class OrdersController < ApplicationController
def create
@order = Order.new(order_params)
authorize! :create, @order
if @order.save
render_order_json
end
end
def order_params
permitted = params.permit(:customer_id, :line_items => line_item_params)
permitted[:line_items_attributes] = permitted.delete("line_items") if permitted["line_items"]
permitted
end
def line_item_params
[:product_id, :variant_id, :quantity]
end
编辑 3:我看到报告的 SQL 示例:
Order Load (1.0ms) SELECT "orders".* FROM "orders" WHERE "orders"."id" = $1 ORDER BY "orders"."id" ASC LIMIT 1 [["id", 1]]
Product Load (1.0ms) SELECT "products".* FROM "products" WHERE "products"."product_id" = $1 AND (season = 'AW14') ORDER BY "products"."id" ASC LIMIT 1 [["product_id", 1423]]
SQL (2.0ms) INSERT INTO "line_items" ("order_id", "price", "product_id", "quantity", "variant_id") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["order_id", 1], ["price", 10.0], ["product_id", 1423], ["quantity", 5], ["variant_id", "1423_101_10"]]
Order Load (1.0ms) SELECT "orders".* FROM "orders" WHERE "orders"."id" = $1 ORDER BY "orders"."id" ASC LIMIT 1 [["id", 1]]
Product Load (2.0ms) SELECT "products".* FROM "products" WHERE "products"."product_id" = $1 AND (season = 'AW14') ORDER BY "products"."id" ASC LIMIT 1 [["product_id", 2396]]
SQL (1.0ms) INSERT INTO "line_items" ("order_id", "price", "product_id", "quantity", "variant_id") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["order_id", 1], ["price", 15.0], ["product_id", 2396], ["quantity", 3], ["variant_id", "2396_101_10"]]
【问题讨论】:
-
您还缺少添加生成数据库查询的控制器代码。
-
我添加了 OrdersController 的简化版本。我希望这已经足够了。
-
你提到的那些数据库查询来自哪里对我来说仍然不是很明显
-
所以您是说应该为每个订单项生成这些查询是不正常的行为?我添加了一个添加订单时在控制台中看到的示例。
-
据我所知,您的代码中没有任何内容可以执行任何查询。获取价格的代码在哪里?
标签: activerecord ruby-on-rails-4