我正在尝试在rails 3中执行简单的Post / Tags关系。 一切正常,除非我想查询与几个标签相关的帖子。 基本上我想做这样的事情:
Post.joins(:tags).where('tags.name ILIKE ?', var)
但是我不想只使用一个var,而是想使用一个数组。 我试过了:
Post.joins(:tags).where('tags.name IN (?)', names_array)
但不幸的是,它做了一个简单的LIKE(而不是ILIKE),并且像OR条件一样,听起来非常合乎逻辑。
我还在这篇文章中使用了find_by_sql找到了另一个解决方案 http://snippets.dzone.com/posts/show/32
但对我来说似乎有点难看。
更好地了解问题。 我有3个帖子: 波斯塔 PostB POSTC
PostA与TagA TagB和TagC标签相关。 PostB与TagA和TagB标签相关。 PostC仅与TagA有关。
如果我查找TagA和TagC帖子,我想找到PostA,因为它与两个标签有关。 使用哈希条件返回PostA PostB和PostC。 我想要的是与“至少”所有指定标签相关的帖子。
所以任何人都有更好的方法来解决这个问题吗?
感谢。
答案 0 :(得分:2)
我不知道它是否会解决您的问题,但对于复杂的查询,我几乎总是只使用Squeel。
然后做这样的事情:
@posts = Post.joins(:tags)
.where{tags.name.like_any names_array}
.group("post_id")
.having("count(post_id) = #{names_array.size}")
SQL希望看起来像这样
SELECT "posts".* FROM "posts"
INNER JOIN "tags" ON "tags"."post_id" = "posts"."id"
WHERE (("tags"."name" LIKE "TagA" OR "tags"."name" LIKE "TagB"))
GROUP BY post_id
HAVING count(post_id) = 2
如果我记得根据使用的数据库,使用ILIKE而不是LIKE非常擅长使用。 (至少比AR好)
你也可以使用没有squeel的AR来做到这一点,但我真的喜欢squeel附带的一些想法和帮助,例如_all
至于探索......
假设我搜索了TagsA和B.
这样做可以找到包含这些标签的所有帖子。
所以你会有类似的东西:
然后它将使用post_id将所有那些不同的Post结果按联合标记分组。
然后它将通过检查有多少forgien_ids来检查SQL行具有的标签数量。 由于A和B有2个标签,因此您知道它与您输入的所有标签相匹配。
答案 1 :(得分:0)
好的,所以我发现没办法避免使用find_by_sql。 这就是我所做的。
@posts = Post.find_by_sql([ "SELECT * FROM posts p
JOIN (
SELECT pt.post_id FROM posts_tags pt
JOIN posts p ON p.id = pt.post_id
JOIN tags t ON t.id = pt.tag_id
WHERE t.label IN (?)
GROUP BY pt.post_id
HAVING count(pt.post_id) = ?
) ct ON c.id = ct.post_id", names_array, names_array.size])
我个人并不完全理解这个查询(在http://www.sergiy.ca/how-to-write-many-to-many-search-queries-in-mysql-and-hibernate/ - #3上找到)。特别是它加入选择的部分。因此,如果有人能够解释这个查询是如何真正有用的话那就太棒了。
此外,如果有人知道如何以更“铁路”的方式(比硬编码查询)这样做,我会喜欢它。
希望这可以帮助一些人。
答案 2 :(得分:0)
我被same problem困住了。 squeel docuemtnation表明这是可能的。在复合条件部分,他列出了三种类似的方法。
鉴于
names = ['Ernie%', 'Joe%', 'Mary%']
然后你可以做
Person.where('name LIKE ? OR name LIKE ? OR name LIKE ?', *names)
或
Person.where((['name LIKE ?'] * names.size).join(' OR '), *names)
或
Person.where{name.like_any names}
文档暗示我们可以使用AND而不是OR或like_all而不是like_any。
然而,我似乎无法让它为habtm关系工作。它不断给我undefined method 'call'
一个ActiveRecord实例。