Поиск в нескольких столбцах - Rails - PullRequest
16 голосов
/ 21 февраля 2012

В настоящее время я пишу метод поиска для моих приложений rails, и в данный момент он работает нормально.У меня в файле game.rb есть следующее:

def self.search(search)
  if search
    find(:all, :conditions => ['game_name LIKE ? OR genre LIKE ? OR console LIKE ?', "%#{search}%", "#{search}", "#{search}"])
  else
    find(:all)
  end
end

Теперь, когда поиск выполняется нормально, но моя проблема в том, что если в game_name есть запись со словом PlayStation, она завершитискать там.Он возвращает только эту запись, а не все игры, в которых «PlayStation» хранится в консоли.Теперь я понимаю, что это потому, что у меня есть «ИЛИ» в моих условиях, но я не знаю альтернативы.«И» требует, чтобы все условия соответствовали или ни одно не возвращалось вообще.Какую альтернативу я могу использовать для И и ИЛИ?Помощь будет высоко ценится.

Если есть решение, которое имеет отдельные поля поиска и записи, тогда это было бы хорошо, я не обязательно требую, чтобы поиск находил все это на основе одной формы поиска.

Ответы [ 5 ]

32 голосов
/ 21 февраля 2012

Если я правильно понимаю ваш вопрос, ваш SQL выглядит хорошо для меня из-за того, что вы пытаетесь сделать. Предложение OR вернет все записи, которые совпадают в column1, column2 или column3. Это не останавливается на первом матче. Я вижу проблему с вашими параметрами в том, что в первый раз вы используете LIKE с%, а во втором - нет, возможно, именно отсюда ваша проблема.

Должна ли это быть ваша находка (% вокруг второго и третьего поиска)?

find(:all, :conditions => ['game_name LIKE ? OR genre LIKE ? OR console LIKE ?', "%#{search}%", "%#{search}%", "%#{search}%"])

или лучше использовать DRY версию (выше не будет работать для Rails 4.2 +):

Item.where('game_name LIKE :search OR genre LIKE :search OR console LIKE :search', search: "%#{search}%")
20 голосов
/ 17 ноября 2014

Что если у вас есть 15 столбцов для поиска, то вы будете повторять клавишу 15 раз. Вместо повторения ключа 15 раз в запросе вы можете написать так:

key = "%#{search}%"

@items = Item.where('game_name LIKE :search OR genre LIKE :search OR console LIKE :search', search: key).order(:name)

Это даст вам тот же результат.

Спасибо

9 голосов
/ 07 июня 2016

Я думаю, что это немного более чистое решение.Это позволяет вам добавлять / удалять столбцы более легко.

key = "%#{search}%"
columns = %w{game_name genre console}
@items = Item.where(
  columns
    .map {|c| "#{c} like :search" }
    .join(' OR '),
  search: key
)
0 голосов
/ 09 ноября 2018

Более общее решение для поиска во всех полях модели будет выглядеть так:

def search_in_all_fields model, text
  model.where(
    model.column_names
      .map {|field| "#{field} like '%#{text}%'" }
      .join(" or ")
  )
end

Или лучше как прицел в самой модели

class Model < ActiveRecord::Base
  scope :search_in_all_fields, ->(text){
    where(
      column_names
        .map {|field| "#{field} like '%#{text}%'" }
        .join(" or ")
    )
  }
end

Вам просто нужно назвать это так

Model.search_in_all_fields "test"

Перед тем, как начать .., нет, SQL инъекция, вероятно, не будет работать здесь, но все же лучше и короче

class Model < ActiveRecord::Base
  scope :search_all_fields, ->(text){
    where("#{column_names.join(' || ')} like ?", "%#{text}%")
  }
end
0 голосов
/ 19 июля 2018

Я думаю, что это более эффективное решение, если вы хотите искать массив столбцов, как я.

Во-первых, и самое главное, вы можете добавить частную функцию к вашей модели, которая создает шаблон запроса:

def self.multiple_columns_like_query(array)
  array.reduce('') { |memo, x|  #
    unless memo == ''           #
      memo += ' or '            #  This is the
    end                         #  
    memo += "#{x} like :q"      #  core part
  }                             #
end                             

Чем вы можете использовать функцию в своей функции поиска:

def self.search(query)
  if fields = self.searched_fields && query
    where multiple_like_query(fields), q: "%#{query}%"
  end
end

Здесь вы также должны определить self.searched_fields как массив имен полей.

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