Как найти сообщения с несколькими тегами - PullRequest
1 голос
/ 23 июля 2011

У меня очень простая модель тегов на 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"], то он должен возвращать все посты с этим тегом (easy), или если ввод ["style", "men"], тогда он должен возвращать все посты с тегом "style" AND " мужчины».

Ответы [ 2 ]

1 голос
/ 23 июля 2011

Существует ли простой способ найти все сообщения, у которых есть еще 2 указанных тега?Например, допустим, есть теги "style", "men", "women", "sale"

Классическим способом является использование сводной таблицы: posts <-> posts_tags <->теги

Вы можете кодировать свои теги вот так, потому что это самый простой способ (поддерживает целостность, внешние ключи, позволяет легко сканировать список тегов и т. д.).

ЭтоУ way есть приличная производительность для небольшого количества постов и небольшого количества тегов, но это громоздкий запрос (вам понадобится некоторая агрегация, INTERSECT или 1 JOIN на тег) и чрезвычайно медленный, если теги не очень избирательны.

Очевидно, что для поиска, который вы хотите выполнить, это отстой.Таким образом, у вас есть 2 варианта:

1 - материализуйте список идентификаторов тегов сообщения внутри столбца INTEGER [] в таблице сообщений, поместите в него индекс gist (или gin) и используйте "integer"Оператор "массив содержит", который индексируется, очень быстро и тривиально для запроса.

2 - просто поместите ваши теги как текст и добавьте к ним полнотекстовый индекс

Оба очень быстрыес преимуществом перед целочисленным массивом.

0 голосов
/ 23 июля 2011

Я мог бы написать действительно плохой SQL здесь, что будет делать JOINS и GROUP BY, но это рельсы, чтобы вы могли работать лучше, сначала ваша модель 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] )
...