我有两个模型Product
和ProductProperties
。因此,我将产品的属性存储在与另一个模型Properties
如何实现查找具有属性(A或B或C)AND(X或Y或Z)的产品的范围
我目前拥有的过滤器就是这样 -
scope :product_type_filter, lambda {|property_id|
return nil if property_id.blank?
joins(:product_properties).where('product_properties.property_id IN (?)', property_id).distinct
}
scope :metal_filter, lambda {|property_id|
return nil if property_id.blank?
joins(:product_properties).where('product_properties.property_id IN (?)', property_id).distinct
}
并产生以下SQL - SELECT DISTINCT "products".* FROM "products" INNER JOIN "product_properties" ON "product_properties"."product_id" = "products"."id" AND "product_properties"."deleted_at" IS NULL WHERE "products"."deleted_at" IS NULL AND (product_properties.property_id IN ('504')) AND (product_properties.property_id IN ('520'))
但它并没有真正起作用,因为它正在寻找一个同时具有值504和520的产品属性,这将永远不会存在。
非常感谢一些帮助!
答案 0 :(得分:1)
所以这是我使用的连接 -
def self.find_with_properties property_ids, group_name
joins(:product_properties).joins('JOIN product_properties '+group_name+' ON '+group_name+'.product_id = products.id AND '+group_name+'.property_id IN ('+property_ids.to_s.tr('[', '').tr(']', '').tr('"', '') +')')
end
答案 1 :(得分:0)
首先,我认为你不应该使用范围来完成这个任务你应该创建一个Class方法来完成它。当涉及复杂逻辑时,不使用范围是最佳实践。
其次,上面提到的代码并没有错。关于把他们称错了。我认为你正在超越范围。
根据定义,上述范围都是相同的,因此您不需要定义两次。试试这个
def self.find_with_properties property_ids
joins(:product_properties).where('product_properties.property_id IN (?)', property_ids)
end
并称之为
Product.find_with_properties([1,2,3]).find_with_properties([4,5,6]).uniq
如果'A' , 'B' , 'C'
是属性名称,那么您应该这样做:
self.find_by_properties_names(property_names)
self.joins(:product_properties=>[:property]).where("properties.name IN(?)",property_names)
end
然后可以像
一样打电话Product.find_by_properties_names(["A","B","C"]).find_by_properties_names(["C","D","E"])
答案 2 :(得分:0)
试试这个
scope :product_type_filter, ->(f_property_ids, s_property_ids) { joins(:product_properties).where('product_properties.property_id IN (?) AND product_properties.property_id IN (?)', f_property_ids, s_property_ids).distinct }
使用2个参数调用scope
@products = Product.product_type_filter([1,2,3], [4,5,6])