Хобрук: Ваш путь к мастерству в программировании

Фильтрация с помощью AND и OR в запросе Rails

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

Size
  [XS]
  [S]

Color
  [Red]
  [Blue]

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

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

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

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

Похоже, что Rails не предоставляет возможности построения запроса ИЛИ. Так что вы должны сделать это самостоятельно. Согласно схеме, Item has_and_belongs_to_many :tags, верно? В 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.

02.03.2012
Новые материалы

Основы принципов S.O.L.I.D, Javascript, Git и NoSQL
каковы принципы S.O.L.I.D? Принципы SOLID призваны помочь разработчикам создавать надежные, удобные в сопровождении приложения. мы видим пять ключевых принципов. Принципы SOLID были разработаны..

Как настроить Selenium в проекте Angular
Угловой | Селен Как настроить Selenium в проекте Angular Держите свое приложение Angular и тесты Selenium в одной рабочей области и запускайте их с помощью Mocha. В этой статье мы..

Аргументы прогрессивного улучшения почти всегда упускают суть
В наши дни в кругах веб-разработчиков много болтают о Progressive Enhancement — PE, но на самом деле почти все аргументы с обеих сторон упускают самую фундаментальную причину, по которой PE..

Введение в Джанго Фреймворк
Схема «работать умно, а не усердно» В этой и последующих статьях я познакомлю вас с тем, что такое фреймворк Django и как создать свое первое приложение с помощью простых и понятных шагов, а..

Настольный ПК как «одно кольцо, чтобы править всеми» домашних компьютеров
Вид после 9 месяцев использования С настольных компьютеров все началось, но в какой-то момент они стали «серверами», и мы все перешли на ноутбуки. В прошлом году я столкнулся с идеей настольных..

Расширенные методы безопасности для VueJS: реализация аутентификации без пароля
Руководство, которое поможет вам создавать безопасные приложения в долгосрочной перспективе Безопасность приложений часто упускается из виду в процессе разработки, потому что основная..

стройный-i18следующий
Представляем стройную оболочку для i18next. Эта библиотека, основанная на i18next, заключает экземпляр i18next в хранилище svelte и отслеживает события i18next, такие как languageChanged,..