在Rails查询中使用AND和OR进行过滤

时间:2012-03-02 07:20:08

标签: mysql sql ruby-on-rails ruby-on-rails-3 tags

我的Rails应用程序中存在一个难以过滤的问题。用户想要使用标签过滤项目。这没问题,我只使用命名范围。但标签出现在用户可以选择的框中,如下所示:

Size
  [XS]
  [S]

Color
  [Red]
  [Blue]

标签位于“tagsets”中,一个标签集为多个标签。

我的问题:当用户想要缩小搜索范围时,如何将多个过滤查询链接在一起?

当用户从第一个框中选择XS时,它应该单独过滤该标记上的结果集。当用户选择XS和S时,我们添加到过滤器并获得更多结果。命名范围仍然不是问题。但是,如果用户想要从第二个框中过滤XS和S然后是红色,该怎么办?当事情变得多毛时 - 我不能只为该标签添加另一个Item.by_tag(“tagname”),它必须是我已经拥有的结果的标签过滤器,缩小结果。

同一标记框中的多个复选框 - 结果更多。检查另一个标签集框 - 结果更少。我尝试为每个标记集框执行一个SELECT,然后在ruby中合并结果集以仅显示所有集合中的匹配,但这打破了分页,因为我永远不知道将返回多少结果。感觉这需要是一个查询,它可能是某种类型的连接,但我不擅长SQL,我无法弄明白。这就是架构的相关部分:

create_table "items" do |t|
  t.string   "title"
end

create_table "items_tags", :id => false do |t|
  t.integer "item_id"
  t.integer "tag_id"
end

create_table "tags" do |t|
  t.string   "title"
  t.integer  "tagset_id"
end

create_table "tagsets" do |t|
  t.string   "title"
end

1 个答案:

答案 0 :(得分:0)

似乎Rails没有提供构建OR查询的方法。所以你必须自己做。 根据模式,一个Item has_and_belongs_to_many:标签,对吧? 在Rails 2.3中,以下named_scopes应该可以工作。如果您使用的是Rails 3,则需要重写它。

named_scope :having_tags, lambda { |tagsets| {:joins => :tags, :select => "DISTINCT items.*",
  :conditions => ([Array.new(tagsets.size, "tags.title IN (?)").join(' OR ')] + tagsets) }

然后你这样称呼它:

Item.having_tags([['XS', 'S'], ['Red', 'Blue']])

我假设您正在使用MySQL。