Как искать в нескольких полях с помощью Searchkick/ES в Rails

Вопрос или проблема

Я проиндексировал поля имени, местоположения и должности в модели Employee. При поиске по термину он должен совпадать с любым из этих полей. Например, если имя Джон, а местоположение Лондон, то поиск по “Джон”, “Джон Лондон” или “Лондон” должен возвращать результаты. Однако поиск по “Джон Лондон” не должен возвращать результаты для “Джон Германия”.

Какие настройки мне нужно реализовать для достижения этого?

Ответ или решение

Для того чтобы осуществлять поиск по нескольким полям модели Employee с использованием библиотеки Searchkick и Elasticsearch в Rails, вам необходимо правильно настроить индексацию и выполнить соответствующие поисковые запросы. Рассмотрим пошагово, как это сделать.

Шаг 1: Настройка индексации

Ваша модель Employee должна быть настроена для индексации полей name, location и designation. Для этого в модели добавьте следующий код:

class Employee < ApplicationRecord
  searchkick word_start: [:name, :location, :designation]

  def search_data
    {
      name: name,
      location: location,
      designation: designation
    }
  end
end

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

Шаг 2: Выполнение поиска

Для выполнения поиска нам нужно использовать метод search из Searchkick. Например, в контроллере можно сделать следующий запрос:

class EmployeesController < ApplicationController
  def index
    if params[:query].present?
      @employees = Employee.search(params[:query], fields: [:name, :location, :designation], misspellings: { below: 5 })
    else
      @employees = Employee.all
    end
  end
end

В этом примере, если параметр query присутствует, будет возвращен результат поиска. Мы указываем, что нужно проводить поиск по полям name, location и designation. Опция misspellings позволяет учитывать небольшие ошибки при вводе.

Шаг 3: Настройка логики поиска

Для того чтобы реализовать нужную вам логику (например, чтобы поиск через «John London» не возвращал «John Germany»), вы можете воспользоваться фильтрацией результатов. Например, можно использовать must и should в запросе:

def index
  if params[:query].present?
    query_terms = params[:query].split
    search_conditions = query_terms.map do |term|
      {
        bool: {
          should: [
            { match: { name: term } },
            { match: { location: term } },
            { match: { designation: term } }
          ]
        }
      }
    end

    @employees = Employee.search(
      { bool: { must: search_conditions } },
      fields: [:name, :location, :designation],
      match: :word_start
    )
  else
    @employees = Employee.all
  end
end

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

Заключение

Следуя приведённым шагам, вы сможете осуществлять поиск в нескольких полях модели Employee с использованием Searchkick и Elasticsearch. Этот подход позволит обеспечить точные результаты поиска в зависимости от введенных пользователем критериев. Не забывайте оптимизировать и настраивать ваш индекс и запросы в зависимости от требования вашего приложения для достижения наилучших результатов поиска.

Оцените материал
Добавить комментарий

Капча загружается...