Драгоценный камень Searchkick и ассоциация exists_to

Следуя инструкциям Searchkick Readme и нескольким примерам, я попытался реализовать довольно простой поиск, используя ассоциацию «members_to». Тем не менее, я не вижу поведения, на которое надеялся, и я надеюсь, что просто упускаю что-то маленькое...

У меня есть модель книги, которая принадлежит автору. Я хотел бы включить поиск по именам книг или именам авторов. Так, например, если бы я искал «Камень», я бы увидел и «Стоун Филлипс» (автор), и «Бросок камня» (книга). Кроме того, если бы я изменил свой поиск на «Каменный луг», это вернуло бы Стоуна Филлипса как автора вместе с его книгой под названием «Мой луг».

Я нашел способ решения для первого примера, но не могу заставить работать второй пример. В настоящее время у меня есть простой pg_search, который с легкостью выполняет оба приведенных выше примера, используя метод «associated_against». Хотя я думал, что Searchkick предоставляет что-то настолько простое, я не могу заставить его работать...

Основные подходы, которые я пробовал:

В моем контроллере

@search = Book.search params[:query],
      limit: 30,
      fields: [:book_name, :author_name], 
      misspellings: false

И в моей модели (сначала просто метод "search_data", позже добавлена ​​область...)

scope :search_import, -> { includes(:author) } 
  
  def search_data
    {
      book_name: book_name,
      author_name: author(&:author_name)
    }
  end

Этот подход по какой-то причине не возвращает никаких результатов по имени автора. Я вижу похожие названия книг только при поиске по одному слову и не вижу результатов при поиске по нескольким словам.

Я также попытался переключить это, чтобы запустить модель автора, которая, кажется, работает лучше, потому что я получаю результаты как для книг, так и для авторов. Тем не менее, я также получаю много результатов мусора, которые не связаны между собой. И я по-прежнему вижу результаты только для поиска по одному слову — нет результатов для поиска по двум словам.

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

@search = Book.search params[:query],
      limit: 30,
      index_name: [Book.searchkick_index.name, Author.searchkick_index.name],
      fields: [:book_name, :author_name], 
      misspellings: false

Это на самом деле обеспечивает лучший набор результатов для одного слова. Он возвращает все ожидаемые имена книг и имена авторов без всего мусора. Но когда я пытаюсь добавить второе слово, чтобы сузить поиск, я не получаю результатов...

Я пробовал ряд других небольших изменений, используя предложения из других постов, туториалов и т. д. И, если кому-то интересно, я всегда переиндексирую после внесения изменений в методы search_data или searchkick.

Я надеюсь, что предоставил достаточно информации, но, пожалуйста, дайте мне знать, если у вас есть вопросы... Я не могу понять, что ускользает от меня. Любая помощь высоко ценится!


person Carl Timm    schedule 13.08.2015    source источник


Ответы (1)


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

class Product
  searchkick word_middle: [:title, :authors]

  def search_data
    {
      title: title,
      authors: authors.map(&:full_name).join('')
    }
  end

  def search_by_title_or_author(term, opts = {})
    search_opts = default_search_opts.merge(opts)
    search term, search_opts.merge(
      operator: 'or',
      fields: [
        [ { 'title^10': :word_middle }, { 'authors': :word_middle } ]
      ]
    )
  end

  protected

  def default_search_opts
    {
      per_page: 10,
      load: false  # we use caching, so don't load from DB by default,
      # we have other defaults as well that we include here
    }
end

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

person Ian Selby    schedule 13.08.2015
comment
Спасибо Ян! Ваш метод соединения и/или оператор, кажется, помогают. Когда я использую их и делаю свою модель Author искомой моделью, я могу выполнять поиск по нескольким словам. Тем не менее, я получаю МНОГО мусора/дополнительных результатов. Тем не менее, когда я устанавливаю свою модель Book в качестве искомой модели и пытаюсь переиндексировать, я получаю сообщение об ошибке NoMethodError: undefined method `join' for #‹Class:0x007fbcda144878›. есть идеи? - person Carl Timm; 14.08.2015
comment
ну, как я уже сказал, в моем примере у меня есть модель, принадлежащая продукту с именем author, у которого есть метод с именем full_name. Поэтому я в основном создаю строку полных имен авторов для индексации (в нашем приложении вводите вперед). Вам нужно будет настроить это в своей структуре данных (например, "#{author.first_name} #{author.last_name}) - person Ian Selby; 14.08.2015