Индексировать результаты метода в 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
хэш во всей цепочке инструментов импорта в Тире.