2013-11-12 2 views
2

начинающему Im в рельсах и есть некоторые проблемы, чтобы улучшить свой поисковый запрос:Поисковый запрос для (имя или личного имени) и (имя forname) и (имя forname)

В контроллере я называю:

def index 
if params[:search] 
    @persons = Person.search(params[:search]).order("created_at DESC") 
else 
    @persons = Person.order("created_at DESC") 
end 
end 

А в модели у меня есть:

def self.search(query) 
    where("name like ?", "%#{query}%") 
end 

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

John 
Smith 
Smith John 
John Smith 

и она всегда должна возвращать John Smith. Итак, как я могу написать такой длинный sql-запрос? Заранее спасибо!

ответ

2

Этот метод поиска должен работать для вас:

def self.search(query) 
    return where('FALSE') if query.blank? 

    conditions = [] 
    search_columns = [ :vorname, :nachname ] 

    query.split(' ').each do |word| 
    search_columns.each do |column| 
     conditions << " lower(#{column}) LIKE lower(#{sanitize("%#{word}%")}) " 
    end 
    end 

    conditions = conditions.join('OR')  
    self.where(conditions) 
end 
  • Этот код безопасен: sanitizes строки перед вызовом SQL
  • Этот код гибок: вы можете очень легко добавить больше столбцов для поиска по
  • Этот код является гибким: вы можете легко разделить на более п только пространство (-/| и т.д.)
  • Этот код может использоваться для цепочки-обзорного
  • Этот код регистронезависимым, будет работать с любым John Smith или JohN SMITh

Не сомневайтесь задавать вопросы, если это необходимо!

+0

Я думаю, что это лучший код, но почему-то я получаю сообщение об ошибке: 'SQLite3 :: SQLException: рядом с« ILIKE »: синтаксическая ошибка: SELECT« пациенты ». * FROM« пациенты »WHERE (vorname ILIKE '%' emmanuel '%' OR nachname ILIKE '%' emmanuel '%') ' –

+0

Извините,' vorname' является forename на немецком языке, а 'nachname' - это имя –

+0

Я обновил свой ответ @JohnSmith. Также я рекомендую вам использовать английский в своих приложениях, его проще поддерживать для другие люди, и это является частью Конвенции об именах Rails;) – MrYoshiji

0

Как насчет того, чтобы делать что-то подобное?

def self.search(query) 
    where("name LIKE ? or forename LIKE ? or concat(name, ', ', forename) LIKE ?", "%#{query}%", "%#{query}%" , "%#{query}%") 
end 

Если ваши поисковые запросы становятся очень сложными вы можете взглянуть на поиск драгоценных камней, таких как elasticsearch

+0

Я получаю сообщение об ошибке: 'SQLite3 :: SQLException: нет такой функции: concat:' –

+0

agh. Я предполагал MySQL. Проверьте это: http://stackoverflow.com/questions/6134415/how-can-we-concatenate-string-in-sqlite, чтобы объединиться с Sqlite3. Сказав это, я думаю, что ответ @MrYoshiji должен быть принят. Действительно приятное решение – Nobita

0

То, что вы должны работать на следующих поисковых запросов

John 
Smith 
John Smith 

Выполните следующие действия, если вы хотите, чтобы он работал для обратных поисковых запросов также

def self.search(query) 
    name_parts = query.split(' ') 
    condition = name_parts.collect{|part| "name like #{sanitize("%#{part}%")}"}.join(' AND ') 
    where(condition) 
end 
+1

Этот код не будет работать для поиска, например '' автомобиль pierre'', - он сломает SQL-запрос из-за цитаты '; Кроме того, «И» не имеет дополнительного места, и SQL будет выглядеть так: '' name like '% whtvr%' ANDname like '% wtr%' ANDname ... "' -> не будет работать – MrYoshiji

+0

Фактически он работает только для 'john John' –

+0

Может быть, вы можете мне помочь с этим? Спасибо http://stackoverflow.com/questions/19937318/better-search-query-for-two-columns-forename-and-name –

Смежные вопросы