搜索has_and_belongs_to_many:标签的模型

时间:2012-03-01 16:26:57

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

我需要一点Rails的帮助。我正在将数据查找服务的后端系统从PHP转移到RoR。我发现这是令人惊讶的简洁。

我需要能够在模型上搜索与标签模型的关系。每个模型都被赋予has_and_belongs_to_many关联。

当用逗号分隔的值列表传入搜索时,我需要对标签执行“AND”搜索,以便找到所有传递了所有标签的资源(即伦敦和桥梁)。

此外,它需要不区分大小写。目前,我只在资源模型中执行了一次标记搜索。

def self.search(search)
    where('LOWER(tags.name) = ?', search.downcase).joins(:tags)
end

我使用wherefindall使用数组的所有尝试均未成功。

在连接表上进行AND搜索的PHP方式看起来相当hacky,我希望Rails可以提供更优雅的解决方案。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:3)

如果您需要AND,则需要确保匹配代码的数量正是您请求的数量,因此也需要COUNT。您要查询的查询将涉及IN

如果您可以确保标签始终以小写字母存储,那将会更方便。如果您拥有大量数据,那么在查询中执行LOWER(...)之类的操作将会遇到麻烦,因为它会导致自动表扫描并且无法编制索引。

其次,我会避免使用has_and_belongs_to_many,因为这是Rails 1.0天的遗物,不像has_many :through替代品那样灵活或可靠。从数据库角度来看,这两种方法之间的唯一区别是:through连接表具有每个条目的唯一ID,并由一流模型表示。 has_and_belongs_to_many系统在很多时候都很古怪,无用。

你可能想要的东西是这样的:

def self.with_all_tags(*tags)
  tags = tags.flatten.collect(&:downcase)
  where('tags.name IN (?)', tags).having('COUNT(tags.id)=?', tags.length).joins(:tags)
end

def self.with_any_tags(*tags)
  tags = tags.flatten.collect(&:downcase)
  where('tags.name IN (?)', tags).joins(:tags)
end

您可能需要进行试验才能获得正确的行为。你的例子不是那么具体。