Rails:对has_many:through的加载和高级查询

时间:2014-07-25 02:56:37

标签: sql ruby-on-rails

概述

每当将新产品添加到数据库时,都会对数据库中的所有现有产品进行检查,以确定它是否可能存在重复。如果发现新添加的产品可能是重复的,则为新添加的产品(pending_product_id)和潜在匹配(existing_product_id)创建DuplicateWarning关联。此外,整数匹配分数存储在DuplicateWarning上,表示两种产品之间潜在匹配的强度。

模型

class Product < ActiveRecord::Base
  has_many :matches, through: :duplicate_warnings, source: :existing_product
  has_many :duplicate_warnings, foreign_key: "pending_product_id", dependent: :destroy
end

class DuplicateWarning < ActiveRecord::Base
  belongs_to :pending_product, class_name: "Product"
  belongs_to :existing_product, class_name: "Product"
end

问题

如何构建以下查询,并包含预先加载?

查找匹配少数产品变量的产品,其中Product.duplicate_warnings.match_score&lt; 5 并确保同一产品没有具有匹配分数&gt;的DuplicateWarnings; 5?

例如:

产品,其中Product.status == 0和Product.manufacturer ==“Toyota”和Product.duplicate_warnings.match_score&lt; 5并确保产品没有带有match_score&gt;的DuplicateWarnings; 5?

1 个答案:

答案 0 :(得分:1)

您希望在您的情况下急切加载什么? 这将查询符合您条件的产品。

Product.joins(:duplicate_warnings).select("products.*, max(duplicate_warnings. match_score) as max_score").where(status: 0, manufacturer: "Toyota").group("products.id").having("max(duplicate_warnings. match_score) < 5")

但是这不会急于加载duplicate_warnings。所以你需要不止一个查询。

或者,您可以先找到要排除的所有产品:

exclude_product_ids = DuplicateWarning.where("match_score > 5").group("pending_product_id").pluck(:pending_product_id)

然后用关联加载它们:     Product.where([“status = 0 AND manufacturer ='Toyota'AND id NOT IN(?)”,exclude_product_ids])。includes(:duplicate_warnings)