如何在包含的关系中使用LIKE

时间:2014-11-28 18:01:17

标签: ruby-on-rails arel

我想使用包含关系的搜索条件,就像下面的

一样
Post.includes(:tags).where( tags: { title: '%token%' }).all

poststags表已与名为post_tag_relations的第3个表相关联。
架构如下所示:

posts
 id: pk
 title: string
 content: text

tags
 id: pk
 title: string

post_tag_relations
 id: pk
 tag_id: integer
 post_id: integer

语法只适用于相同的条件,我真的不知道如何使用LIKE搜索条件。

使用Post.joins(:tags)Tag.area_table[:title].matches('%token%')时,它会正常工作,但有些没有标记的帖子将无法取出。

有人能帮帮我吗?非常感谢。


更新

Rails版本是4.1。

我想搜索posts.title LIKE '%token%' OR tags.title LIKE '%token%'之类的帖子,因此如果某些帖子没有标签,则使用Post.joins(:tags)将无效。所以我需要使用Post.includes(:tags)代替。


再次更新

看起来不能使用一个查询来获取,所以我已经尝试了另一个数据库模式......

3 个答案:

答案 0 :(得分:0)

这样的事情:

Post.includes(:tags).where( "tags.title LIKE ?", "%#{token}%" )

可行。 (语法可能有点不对,抱歉,但你明白了)

答案 1 :(得分:0)

为什么不这样做:

Post.includes(:tags).where(Tag.arel_table[:title].matches('%token%').or(Tag.arel_table[:post_id].eq(nil)))

答案 2 :(得分:0)

joins operation is used in all cases before the includes operation during performance以来,但由于includes使用LEFT OUTER JOIN运算符,您应该使用它。您可能还需要使用LEFT,但FULL加入。所以尝试使用 gem:

class Post
   scope :with_token(token), -> do |token|
      re = Regexp.union(token).to_s
      cond = Arel.sql("title REGEXP ? OR content REGEXP ?", re, re)
      includes(:tags).where(Tag.arel_table[:title].eq(token).or(cond))
   end
end

当然原始条件可以替换为使用LIKE运算符:

class Post
   scope :with_token(token), -> do |token|
      includes(:tags).where(arel_table[:title].matches("%#{token}%")
         .or(arel_table[:content].matches("%#{token}%")
         .or(Tag.arel_table[:title].eq(token))))
   end
end

注意:如果有错误,请提供结果SQL。