在以下设置中,客户通过标记具有许多标记。
class Customer
has_many :taggings
has_many :tags, through: :taggings
end
class Tagging
belongs_to :tag
belongs_to :customer
end
我试图在Postgres的Rails中执行的查询是查找具有至少一个标签但没有标签A或B的所有客户。
由于有成千上万的客户,因此需要考虑性能。
答案 0 :(得分:0)
获取标签A和B的ID
ids_of_tag_a_and_b = [Tag.find_by_title('A').id, Tag.find_by_title('B').id]
查找具有至少一个标签但没有标签A或B的所有客户。
#Customer.joins(:tags).where.not("tags.id in (?)", ids_of_tag_a_and_b)
Customer.joins(:tags).where.not("tags.id = ? OR tags.id = ?", tag_id_1, tag_id_2)
答案 1 :(得分:0)
让tag_ids
是A和B ID的数组:
tag_ids = [a.id, b.id]
然后,您需要找到带有A或B标签的客户:
except_relation = Customer.
joins(:tags).
where(tags: { id: tag_ids }).
distinct
并将它们从具有至少一个标签的标签中排除:
Customer.
joins(:tags).
where.not(id: except_relation).
distinct
由INNER JOIN
产生的 .joins
删除了没有标签的客户,并且是复制的来源,因此需要distinct
。
UPD :当需要性能时,可能必须更改数据库架构,以避免额外的联接和索引。
您可以搜索jsonb
标签实现的示例。
答案 2 :(得分:0)
请尝试以下查询。
Customer.distinct.joins(:taggings).where.not(id: Customer.joins(:taggings).where(taggings: {tag_id: [tag_id_a,tag_id_b]}).distinct )
说明。
联接将触发内部联接查询,并确保您仅获得那些至少具有与其关联的标签的客户。
where.not
将照顾您的其他状况。
希望这会有所帮助。