0

我想要按标签搜索的等价物,所以我需要一个exists查询,但我仍然需要在所有标签上留下连接。我尝试了几种方法,但我没有想法。

Qustion - Tag 关系是通过has_and_belongs_to_many两种方式(即我有一个 QuestionTags joiner 表)

例如

Question.join(:tags).where('tag.name = ?', tag_name).includes(:tags)

我希望这能满足我的需要,但实际上它只是将 theincludes与 the混合在一起,join而我最终基本上得到了一个内部连接。

Question.includes(:tags)
   .where("exists (
               select 1 from questions_tags 
                where question_id = questions.id 
                  and tag_id = (select id 
                                  from tags 
                                 where tags.name = ?))", tag_name) 

这会获取正确的结果,但是 a) 真的很难看,并且 b) 给出了弃用警告,因为它似乎又将 与 混淆includesjoin

弃用警告:看起来您正在急切地加载在字符串 SQL sn ippet 中引用的表(其中之一:问题、标签)。例如:

Post.includes(:comments).where("comments.title = 'foo'")

注意我正在尝试将这些写为命名范围。

如果问题不清楚,请告诉我。提前致谢。

4

2 回答 2

1

好的,我知道了。我知道没有内置的语法来做到这一点。我以前使用过另一种方法,您可以这样做:

Question.include(:tags).where("questions.id IN (
#{ Question.joins(:tags).where('tags.name = ?', tag_name).select('questions.id').to_sql})")

您还可以将此子查询加入到您的问题表中,而不是使用 IN。或者,如果您不反对添加 gem 并且您正在使用 Postgres,请使用此gem。它为高级查询提供了非常简洁的语法。

于 2013-10-12T20:29:38.050 回答
0

使用preload代替includes

Question.preload(:tags).where("exists ....

于 2014-03-11T13:34:38.537 回答