【问题标题】:How to find posts with multiple tags如何查找具有多个标签的帖子
【发布时间】:2011-07-23 03:14:40
【问题描述】:

我在 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”、“men”、“women”、“sale”标签。我想创建一个接受标签数组的通用 find 语句。因此,如果输入是 ["style"] 那么它应该返回所有带有该标签的帖子(简单)或者如果输入是 ["style", "men"] 那么它应该返回所有带有标签 "style" AND "的帖子男人”。

【问题讨论】:

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


    【解决方案1】:

    有没有一种简单的方法可以找到所有具有 2 个以上指定标签的帖子? 例如,假设有“style”、“men”、“women”、“sale”标签

    经典的方法是使用数据透视表:posts posts_tags tags

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

    这种方式对于少量帖子和少量标签具有不错的性能,但查询起来很麻烦(您需要一些聚合、INTERSECT 或每个标签 1 个 JOIN)并且如果标签不存在则非常慢非常有选择性。

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

    1- 在您的帖子表的 INTEGER[] 列中具体化帖子的标签 ID 列表,在其上放置一个 gist(或 gin)索引,并使用“包含整数数组”操作符,该操作符被索引,速度极快,查询起来也很简单。

    2- 只需将您的标签作为文本并在其上添加全文索引

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

    【讨论】:

      【解决方案2】:

      我可以在这里写一个非常糟糕的 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 创建 Tagging 时,它都会增加 taggings_count 值,您可以在查询中使用它来有效地查找具有两个或多个标签的帖子:

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

      【讨论】:

      • 对不起...这不是我想要的。我会编辑我的帖子,让我的问题更清楚:) 谢谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多