所以我的产品具有多种功能,并且功能属于feature_key和feature_value。
以下是我正在运行的查询:
Product.family_features.joins(:feature_key, :feature_value)
.where(feature_keys: { name: ["Color", "Size"] }, feature_values: { name: ["Red", "Large"] })
.group_by(&:product_id)
注意:.family_features
是产品的范围,可获取与产品"家庭"相关的所有功能。 - 这是一组其他产品。
现在我只想要一种产品具有“#color;" color" => "红色"和"尺寸" => "大"
但我得到的功能有"颜色" => "红色"和其他尺寸,以及"尺寸" => "大"和其他颜色。
有没有办法将此查询约束为我需要的确切值组合?
关系看起来像这样:
Product has_many :features
Feature belongs_to :product, :feature_key, :feature_value
FeatureKey has_many :features, :products (through features)
FeatureValue has_many :features, :products (through features)
答案 0 :(得分:0)
您应该可以使用arel。
执行此操作
fkt, fvt = FeatureKey.arel_table, FeatureValue.arel_table
color_red = fkt[:name].eq('Color').and(fvt[:name].eq('Red'))
size_large = fkt[:name].eq('Size').and(fvt[:name].eq('Large'))
Feature.joins(:feature_key, :feature_value)
.where(color_red.or(size_large))
.group(:product_id)
我没有测试过代码,但我认为它应该可行。 查看arel documentation了解详情。
请注意,我还将group_by
更改为group
。 group_by
是Enumerable
模块Ruby方法,而group
是执行SQL GROUP BY
的ActiveRecord关系方法,它应该比Ruby中的分组快得多。
编辑:
虽然您的评论说它有效但如果您需要所有具有size => large
和color => red
组合的产品,我认为这不是您想要的。
您可以尝试这样的事情:
red_products = Product.joins(features: [:feature_key, :feature_value]).where({feature_keys: { name: 'color' }, feature_values: { name: 'red' }})
large_products = Product.joins(features: [:feature_key, :feature_value]).where({feature_keys: { name: 'size' }, feature_values: { name: 'large' }})
products = red_products & large_products
上述解决方案的问题是&
是Ruby中的数组交集,因此它将进行两次数据库查询,并将结果与Ruby相交,这可能会成为大型数据集的问题。