2013-10-12 49 views
0

我想通过标记进行搜索,所以我需要一个exists查询,但我仍然需要在所有标记上加入连接。我尝试了几种方法,并且我没有想法。Rails ActiveRecord在指定范围内通过标记查找问题

的Qustion - 标签关系是通过has_and_belongs_to_many两种方式(即我有一个QuestionTags木匠表)

例如

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

我希望它可以做什么,我需要的,但实际上它只是捣烂了includesjoin和我刚刚结束了与基本内连接。

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) 

此获取正确的结果,但一)实在是太丑了,和b)给出了一个折旧的警告,又似乎混淆includesjoin

弃用警告:看起来你是在字符串SQL sn ippet中引用的热切加载表(一个 :questions,tags)。对于 例如:

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

注意我试图写这些的命名范围。

让我知道如果问题不明确。提前致谢。

+0

说实话,我很困惑,为什么内部联接是不是你不够好,你能请到更详细为什么加入标签工作不适合你? –

+0

@EdgarsJekabsons,因为我需要显示所有带有特定标签的问题列表,但在该列表中仍需要显示每个问题的所有标签,避免N + 1查找。例如。点击上面的'sql'标签来查看我需要的SO页面。只有内部连接,页面将只显示每个问题下的'sql'标签。 – fearofawhackplanet

回答

1

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

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

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

+0

谢谢,这个工程,但我再次得到弃用警告,有没有办法解决这个问题? – fearofawhackplanet

+0

你尝试过'where'方法后面添加includes吗? –

+0

是的,它没有区别。即使是与不相关的包含内容,我也会收到此警告。 'Question.tagged( “SQL”)包括(:投票)'。在我看来,一个错误的轨道,我有同样的问题,同时具有'加入'和'includes'的任何查询。 – fearofawhackplanet

0

使用preload而不是includes

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