如何查找包含多个标签的帖子

时间:2011-07-23 03:14:40

标签: sql ruby-on-rails postgresql activerecord rails-postgresql

我在Rails上使用postgresql有一个非常简单的标记模型:

class Tag < ActiveRecord::Base
  has_many :taggings
  has_many :posts, :through => :taggings, 
                   :source => :tagged, :source_type => 'Post'
end

class Tagging < ActiveRecord::Base
  belongs_to :tag 
  belongs_to :tagged, :polymorphic   => true  
end

class Post < ActiveRecord::Base
  has_many :taggings, :as => :tagged
  has_many :tags, :through => :taggings 
end

是否有一种简单的方法可以查找包含2个指定标签的所有帖子?例如,假设有“风格”,“男人”,“女人”,“销售”等标签。我想创建一个带有标签数组的通用查找语句。因此,如果输入是[“style”],那么它应该返回带有该标签的所有帖子(简单),或者如果输入是[“style”,“men”]那么它应该返回标签为“style”AND“的所有帖子”男人”。

2 个答案:

答案 0 :(得分:1)

  

是否有一种简单的方法可以查找包含2个指定标签的所有帖子?   例如,假设有“风格”,“男人”,“女人”,“销售”的标签

经典的方法是使用数据透视表:posts&lt; - &gt; posts_tags&lt; - &gt;标签

你可以像这样对你的标签进行编码,因为它是最简单的方法(保持完整性,外键,为你提供一个易于扫描的标签列表等)。

这种方式对于少量帖子和少量标签具有不错的性能,但是查询很麻烦(每个标签需要一些聚合,INTERSECT或1个JOIN),如果标签不是,则速度极慢很有选择性。

显然,对于您想要执行的搜索类型,这很糟糕。所以你有两个选择:

1-在posts表的INTEGER []列中实现帖子的标签id列表,在其上放置一个gist(或gin)索引,并使用“包含整数数组”运算符,该运算符已编入索引,非常快,而且很容易查询。

2-只需将您的标记作为文本并在其上投放全文索引

两者都非常快,对整数数组有优势。

答案 1 :(得分:0)

我可以在这里写一个非常糟糕的SQL,它会做什么JOINS和GROUP BY,但这是rails,所以你可以做得更好,首先你的Post模型应该像这样定义:

class Post < ActiveRecord::Base
  has_many :taggings, :as => :tagged, :couter_cache => true
  has_many :tags, :through => :taggings 
end

您需要迁移才能将 taggings_count 列添加到帖子表中:

add_column :posts, :taggings_count, :integer, :default => 0
add_index :posts, :taggings_count

每当为Post创建标记时,它会增加taggings_count值,您可以在查询中使用它来有效地查找包含两个或更多标记的帖子:

Post.all( :conditions => [ 'taggings_count >= ?' 2] )