Фильтрация с помощью AND и OR в запросе Rails - PullRequest
2 голосов
/ 02 марта 2012

У меня сложная проблема с фильтрацией в приложении Rails. Пользователь хочет фильтровать элементы, используя теги. Это не проблема, я просто использую именованную область. Но теги поставляются в ящиках, из которых пользователь может выбирать, например:

Size
  [XS]
  [S]

Color
  [Red]
  [Blue]

Теги находятся в "tagsets", один набор для многих тегов.

Мой вопрос: как объединить несколько запросов фильтра, когда пользователь хочет сузить поиск?

Когда пользователь выбирает XS из первого поля, он должен отфильтровать набор результатов только по этому тегу. Когда пользователь выбирает XS и S, мы добавляем фильтр и получаем больше результатов. Все еще не проблема с именованной областью. Но что, если пользователь захочет отфильтровать XS и S, а затем красный цвет из второго поля? Вот когда все становится неоправданно - я не могу просто добавить другой Item.by_tag ("tagname") для этого тега, это должен быть фильтр тегов для результатов, которые у меня уже есть, сужая результаты вниз.

Несколько флажков в одном и том же поле набора тегов - больше результатов. Проверка в другом поле tagset - меньше результатов. Я попытался сделать один SELECT для каждого блока tagset, а затем объединить наборы результатов в 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 голосов
/ 02 марта 2012

Похоже, что Rails не предоставляет способ построить запрос OR.Таким образом, вы должны сделать это самостоятельно.В соответствии со схемой, элемент 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...