在 ElasticSearch (Tire + ActiveRecord) 中索引一个方法的结果 [英] Index the results of a method in ElasticSearch (Tire + ActiveRecord)

查看:21
本文介绍了在 ElasticSearch (Tire + ActiveRecord) 中索引一个方法的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Tyre 和 ActiveRecord 为 elasticsearch 索引数据集.我有一个艺术家模型,它有_many :images.如何索引返回特定图像的 Artist 模型的方法?或者参考相关模型的方法?我想要的艺术家结果将包括与艺术家关联的主图像的路径(原始图像和缩略图).

I'm indexing a data set for elasticsearch using Tire and ActiveRecord. I have an Artist model, which has_many :images. How can I index a method of the Artist model which returns a specific image? Or alternatively reference a method of the associated model? My desired Artist result will include the paths for the primary Image associated with the Artist (both the original and the thumbnail).

我试过这种映射:

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

引用这些艺术家方法:

    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 的关联,我试过这个:

This just ignores the indexed methods. Based on other answers like Elasticsearch, Tire, and Nested queries / associations with ActiveRecord, I tried this:

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

但这也没有返回我所追求的.我花了几个小时在谷歌上搜索和阅读 elasticsearch 和 Tyre 文档,但没有找到可以遵循的这种模式的工作示例.感谢您的想法!

But this also doesn't return what I'm after. I've spent several hours googling and reading the elasticsearch and Tire documentation and haven't found a working example of this pattern to follow. Thanks for your ideas!

推荐答案

所以,在这里包含您对索引问题的解决方案.

So, to include your solution to the indexing problem here.

索引方法的一种方法是将其包含在 to_json 调用中:

One way to index a method is to include it in the to_json call:

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

另一个更好的方法是在映射块中使用 :as 选项:

Another one, and more preferable, is to use the :as option in the mapping block:

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 指南中的 Eager Loading Associations.

Fighting n+1 queries when importing

The problem with slow indexing is most probably due to n+1 queries in the database: for every artist you index, you issue a query for images (original and thumbnail). A much more performant way would be to join the associated records in one query; see Eager Loading Associations in Rails Guides.

Tire Index#import 方法,和导入 Rake 任务,允许您传递参数,然后将这些参数发送到分页方法.

The Tire Index#import method, and the import Rake task, allow you to pass parameters which are then sent to the paginate method down the wire.

那么让我们比较一下幼稚的方法:

So let's compare the naive approach:

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 片段时:

And when we pass the include fragment:

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))

好多了 :) 请尝试一下,如果它解决了您的问题,请告诉我.

Much better :) Please try it out and let me know if it solves your issue.

您也可以在 Rails 控制台中试用:Article.importArticle.import(include: ['comments']).作为旁注,这个确切的问题是在 Tire 的整个导入工具链中支持 params 哈希的原因.

You can also try it out in the Rails console: Article.import vs. Article.import(include: ['comments']). As a side note, this exact problem was the reason for supporting the params hash in the whole importing toolchain in Tire.

这篇关于在 ElasticSearch (Tire + ActiveRecord) 中索引一个方法的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆