我觉得这是一个常见的问题,但我不完全确定如何表达我试图解决的问题:
我有两个模型:
项目和标签
每一项has_many标签
如果我按标签过滤商品,假设我想找到所有带有"TAG X& TAG Y“或"TAG B& TAG C”的商品,那么这个查询在ActiveRecord中会是什么样子呢?
发布于 2015-05-29 08:40:17
假设您用于标识Tag的列名为name,您可以添加一个方法,如下所示:
class Item < ActiveRecord::Base
has_and_belongs_to_many :tags
# Query via raw SQL
def self.tagged(*tag_sets)
tag_sets.map { |tag_names|
joins(:tags).
where('tags.name' => tag_names).
group('items.id').
having("count(*) = #{tag_names.size}").to_sql
}.join(' UNION ')
find_by_sql(big_query)
end
# Query via Arel
def self.tagged_using_arel(*tag_sets)
items_table = arel_table
union = tag_sets.map { |tag_names|
joins(:tags).
where('tags.name' => tag_names).
group('items.id').
having("count(*) = #{tag_names.size}")
}.reduce { |acc, rel| acc.union(rel) }
from(items_table.create_table_alias(union, :items))
end
end
items = Item.tagged(%W[X Y], %W[Z])请注意,由于Rails目前无法与OR合并关系,因此上面的代码有点混乱(即播放原始SQL或Arel)。这份礼物马上就要到了,in Rails 5。
下面是使用arel编写的与上面相同的代码:
发布于 2015-05-29 20:04:19
为什么不像这样简单的事情呢
class Item
has_many :tags
scope :by_tags, ->(tag_set){
tag_set.each_with_object(scoped) do |tag, ar|
ar.by_tag(tag)
end
}
scope :by_tag, ->(tag){
joins(:tags).where(tags:{ name: tag })
}这将作为AND子句加入它们,并且可以用
Item.by_tags(['X','Y'])https://stackoverflow.com/questions/30519233
复制相似问题