如何在Rails和Postgresql中查找标记有多个标记的post

我有模型PostTagPostTag 。 post通过post标签有很多标签。 我想找到专门标记有多个标签的post。

 has_many :post_tags has_many :tags, through: :post_tags 

例如,给定此数据集:

 posts table -------------------- id | title | -------------------- 1 | Carb overload | 2 | Heart burn | 3 | Nice n Light | tags table ------------- id | name | ------------- 1 | tomato | 2 | potato | 3 | basil | 4 | rice | post_tags table ----------------------- id | post_id | tag_id | ----------------------- 1 | 1 | 1 | 2 | 1 | 2 | 3 | 2 | 1 | 4 | 2 | 3 | 5 | 3 | 1 | 

我想找到标有tomatobasilpost。 这应该只返回“心脏燃烧”post(id 2)。 同样,如果我查询用tomatopotato标记的post,它应该返回“Carb overload”post(id 1)。

我尝试了以下方法:

 Post.joins(:tags).where(tags: { name: ['basil', 'tomato'] }) 

SQL

 SELECT "posts".* FROM "posts" INNER JOIN "post_tags" ON "post_tags"."post_id" = "posts"."id" INNER JOIN "tags" ON "tags"."id" = "post_tags"."tag_id" WHERE "tags"."name" IN ('basil', 'tomato') 

这将返回所有三个post,因为所有post都共享标签tomato。 我也试过这个:

 Post.joins(:tags).where(tags: { name 'basil' }).where(tags: { name 'tomato' }) 

SQL

 SELECT "posts".* FROM "posts" INNER JOIN "post_tags" ON "post_tags"."post_id" = "posts"."id" INNER JOIN "tags" ON "tags"."id" = "post_tags"."tag_id" WHERE "tags"."name" = 'basil' AND "tags"."name" = 'tomato' 

这不返回任何记录。

如何查询标记有多个标签的post?

您可能希望在此答案中查看编写此类查询的可能方法, 以便将条件应用于连接中的多个行 。 这是使用1B,子查询方法在Rails中实现查询的一种可能选项…

PostTag模型中定义一个查询,该查询将获取给定Tag名称的Post ID值:

 # PostTag.rb def self.post_ids_for_tag(tag_name) joins(:tag).where(tags: { name: tag_name }).select(:post_id) end 

Post模型中定义一个查询,该查询将使用子查询结构获取给定Tag名称的Post记录:

 # Post.rb def self.for_tag(tag_name) where("id IN (#{PostTag.post_ids_for_tag(tag_name).to_sql})") end 

然后你可以使用这样的查询:

 Post.for_tag("basil").for_tag("tomato") 

使用方法。包括,像这样:

 Item.where(xpto: "test") .includes({:orders =>[:suppliers, :agents]}, :manufacturers) 

文档到.includes here 。