首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Rails 3多对多查询条件

Rails 3多对多查询条件
EN

Stack Overflow用户
提问于 2012-01-04 20:03:32
回答 3查看 2.8K关注 0票数 2

我试着在Rails3中做一个简单的Post/tag关系,除了我想查询与几个标签相关的Post时,一切都很好。基本上我想做这样的事情:

代码语言:javascript
复制
Post.joins(:tags).where('tags.name ILIKE ?', var)

但我希望使用数组,而不是只有一个var。我试过了:

代码语言:javascript
复制
Post.joins(:tags).where('tags.name IN (?)', names_array)

但不幸的是,它做了一个简单的LIKE (不是ILIKE),并且工作起来像一个OR条件,这听起来非常合乎逻辑。

我还在这篇http://snippets.dzone.com/posts/show/32中使用find_by_sql找到了另一种解决方案

但在我看来有点丑陋。

为了更好地理解这个问题。我有3个帖子: PostA PostB PostC

PostA与TagA TagB和TagC标签相关。PostB与TagA和TagB标签相关。PostC只与TagA相关。

如果我查找TagA和TagC帖子,我希望找到PostA,因为它与这两个标签都相关。使用散列条件将返回PostA、PostB和PostC。我想要的是与“至少”所有指定的标签相关的帖子。

那么谁有更好的办法来处理这件事?

谢谢。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-01-06 04:02:34

我不知道它是否能解决您的问题,但是对于像这样的复杂查询,我几乎总是只使用Squeel

然后这样做:

代码语言:javascript
复制
@posts = Post.joins(:tags)
  .where{tags.name.like_any names_array}
  .group("post_id")
  .having("count(post_id) = #{names_array.size}")

希望SQL看起来像这样

代码语言:javascript
复制
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

如果我没记错的话,根据所使用的数据库,squeel非常擅长使用ILIKE而不是LIKE。(至少比AR好)

你也可以在没有squeel的情况下使用AR来做到这一点,但我真的很喜欢squeel附带的一些想法和助手,比如_all

至于解释..。

假设我搜索了TagsA和B。

它所做的就是找到所有带有这些标签的帖子。

所以你会得到类似这样的东西:

  • PostA TagA
  • PostA TagB
  • PostB TagA
  • PostB TagB
  • PostC TagA

然后,它将使用post_id将所有这些不同的Post结果按照连接的标签进行分组。

  • PostA TagA TagB
  • PostB TagA TagB
  • PostC TagA

然后,它将通过检查存在多少个forgien_ids来检查SQL行中包含的标记的数量。因为A和B有两个标签,你知道它匹配你输入的所有内容。

票数 2
EN

Stack Overflow用户

发布于 2012-01-05 21:57:01

好的,所以我找不到避免find_by_sql的方法。这就是我所做的。

代码语言:javascript
复制
@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上找到)。尤其是它连接select的那部分。因此,如果有人能解释这个查询是如何真正工作的,那就太好了。

此外,如果有人知道如何用更"rails“的方式(而不是硬编码查询)来做这件事,我会很高兴的。

希望这对一些人有帮助。

票数 0
EN

Stack Overflow用户

发布于 2012-08-21 08:02:36

我被same problem卡住了。squeel docuemtnation认为这是可能的。在复合条件部分,他列出了做类似事情的三种方法。

给定的

代码语言:javascript
复制
names = ['Ernie%', 'Joe%', 'Mary%']

然后你可以这样做

代码语言:javascript
复制
Person.where('name LIKE ? OR name LIKE ? OR name LIKE ?', *names)

代码语言:javascript
复制
Person.where((['name LIKE ?'] * names.size).join(' OR '), *names)

代码语言:javascript
复制
Person.where{name.like_any names}

文档暗示我们可以使用AND而不是OR或like_all,而不是like_any。

然而,我似乎不能让它在habtm关系中工作。它一直给我一个ActiveRecord实例的undefined method 'call'

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8726564

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档