Индексировать результаты метода в ElasticSearch (Tire + ActiveRecord)

Я индексирую набор данных для asticsearch, используя Tire и ActiveRecord. У меня есть модель Artist, которая has_many: изображения. Как я могу индексировать метод модели Artist, который возвращает определенное изображение? Или альтернативно ссылаться на метод связанной модели? Мой желаемый результат Исполнитель будет включать пути для основного изображения, связанного с Исполнителем (как оригинал, так и миниатюра).

Я пробовал это отображение:

mapping do
  indexes :id,                  :index    => :not_analyzed
  indexes :name                     
  indexes :url
  indexes :primary_image_original       
  indexes :primary_image_thumbnail
end

для ссылки на эти методы Artist:

    def primary_image_original  
        return images.where(:priority => 'primary').first.original
    end

    def primary_image_thumbnail
        return images.where(:priority => 'primary').first.thumbnail_150
    end

Это просто игнорирует проиндексированные методы. Основываясь на других ответах, таких как Elasticsearch, Tire и вложенные запросы / ассоциации с ActiveRecord, я попробовал это:

mapping do
  indexes :id,                  :index    => :not_analyzed
  indexes :name 
  indexes :url
  indexes :images do
    indexes :original
    indexes :thumbnail_150
    indexes :priority
  end
end

def to_indexed_json
    to_json(include: { images: { only: [:original, :thumbnail_150, :priority] } } )
end

Но это также не возвращает то, что я после. Я потратил несколько часов на поиски в Google и читал документацию эластичного поиска и шин и не нашел рабочего примера этого шаблона. Спасибо за ваши идеи!

1 ответ

Итак, чтобы включить ваше решение проблемы индексации здесь.

Индексирование ассоциаций

Один из способов индексации метода - включить его в to_json вызов:

def to_indexed_json
  to_json( 
    :only   => [ :id, :name, :normalized_name, :url ],
    :methods   => [ :primary_image_original, :primary_image_thumbnail, :account_balance ]
  )
end

Еще одним, и более предпочтительным, является использование :as опция в блоке сопоставления:

mapping do
  indexes :id, :index    => :not_analyzed
  indexes :name             
  # ...

  # Relationships
  indexes :primary_image_original, :as => 'primary_image_original'
  indexes :account_balance,        :as => 'account_balance'
end

Борьба с n+1 запросами при импорте

Проблема с медленной индексацией, скорее всего, связана с n+1 запросами в базе данных: для каждого индексируемого исполнителя вы создаете запрос для изображений (оригинал и эскиз). Гораздо более эффективным способом было бы объединить связанные записи в одном запросе; см. Жесткие ассоциации загрузки в Руководствах Rails.

Шина Index#import метод и задача импорта Rake позволяют передавать параметры, которые затем отправляются в метод paginate, по проводам.

Итак, давайте сравним наивный подход:

bundle exec rake environment tire:import CLASS=Article FORCE=true
Article Load (7.6ms)  SELECT "articles".* FROM "articles" LIMIT 1000 OFFSET 0
Comment Load (0.2ms)  SELECT "comments".* FROM "comments" WHERE ("comments".article_id = 1)
Comment Load (0.1ms)  SELECT "comments".* FROM "comments" WHERE ("comments".article_id = 2)
...
Comment Load (0.3ms)  SELECT "comments".* FROM "comments" WHERE ("comments".article_id = 100)

И когда мы передаем include фрагмент:

bundle exec rake environment tire:import PARAMS='{:include => ["comments"]}'  CLASS=Article FORCE=true 
Article Load (8.7ms)  SELECT "articles".* FROM "articles" LIMIT 1000 OFFSET 0
Comment Load (31.5ms) SELECT "comments".* FROM "comments" WHERE ("comments".article_id IN (1,2, ... ,100))

Намного лучше:) Пожалуйста, попробуйте и дайте мне знать, если это решит вашу проблему.


Вы также можете попробовать это в консоли Rails: Article.import против Article.import(include: ['comments']), Как примечание, именно эта проблема была причиной поддержки params хэш во всей цепочке инструментов импорта в Тире.

Другие вопросы по тегам