在Ruby中查询has_and_belongs_to_many关联

时间:2015-01-01 01:20:20

标签: mysql ruby-on-rails ruby sqlite has-and-belongs-to-many

行。我想要实现的是基于根据特定文章生成相关文章的列表,并且我希望基于与文章相关联的类别获得这些相关文章。我在这两个模型之间有一个简单的habtm关系:文章和类别(连接表名为articles_categories)。我想基于与一篇文章具有相同category_id的文章来创建相关文章查询。例如,文章#1与类别#1和类别#2相关联。我想编写一个查询文章#1的类别ID的查询,然后在文章模型中查询与那些相同类别,类别#1和类别#2相关联的所有文章。我已经在阳光下尝试了一切,似乎无法弄清楚这一点。我尝试了.join各种各样的陈述,似乎没有任何作用。我试着将其分解为以下两部分:

我可以抓住我想要引用的特定文章的所有类别ID,如下所示:

article_cat_ids = @article.category_ids

第二部分是基于这些类别ID的文章过滤器,但我无法弄清楚这一部分。

所以我的问题是,如何获得与数组article_cat_ids中的类别ID相关联的一系列文章。作为奖励踢球者,我希望排除我最初引用的特定文章来创建article_cat_ids,以便文章列表中不包含我试图获取相关文章的文章。

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

听起来很有趣。我认为你的数据模型很棒。

让我们先尝试在SQL中执行此操作。这将指导我们使用ActiveRecord解决方案。

select a1.id
from articles a1
inner join articles_categories ac1 on ac1.article_id = a1.id
inner join articles_categories ac2 on ac2.category_id = ac1.category_id
inner join articles a2 on a2.id = ac2.article_id
where a2.id = $1
  and a1.id <> $1;

这样可行,但您也可以使用IN子句子查询。您应该进行一些基准测试,以确定哪种方法可以更好地处理您的数据。

现在,我们如何将其转换为ActiveRecord?老实说,你可能不想。无论如何,你最终还是会编写很多SQL。

article_id = 1 # or whatever
Article.
  joins('articles_categories ac1 on ac1.article_id = articles.id').
  joins('articles_categories ac2 on ac2.category_id = ac1.category_id').
  joins('articles a2 on a2.id = ac2.article_id').
  where(['a2.id = ? and a1.id <> ?', article_id])

AR在这些情况下是一个漏洞抽象。这应该可行,但在我看来,它比普通SQL的可读性差。

请注意,此解决方案是单个查询。请注意涉及多个查询的其他解决方案。如果您使用,例如,在此处使用1 + N查询问题很容易。红宝石中的循环。