在SearchKick的已加载记录中获取ElasticSearch文档字段

时间:2019-11-05 08:08:59

标签: searchkick

是否可以在已加载的AR记录中获取ElasticSearch文档字段?

以下是要点,可以说明我的意思:https://gist.github.com/allomov/39c30905e94c646fb11637b45f43445d

在这种情况下,我想避免在获得ES响应后total_price的额外计算。我目前看到的解决方案是包括该关系并为每个记录运行total_price计算,这并不是执行此操作的最佳方法,

result = Product.search("test", includes: :product_components).response
products_with_total_prices = result.map do |product|
  {
    product: product
    total_price: product.product_components.map(&:price).compact.sum
  }
end

请问是否可以将ES文档字段混入AR加载记录中?

2 个答案:

答案 0 :(得分:1)

据我所知,不可能获得将文档字段合并到加载的记录中的响应。

通常,我宁愿尽可能地完全依赖索引文档中的数据(使用load: false作为搜索选项),并在必要时仅加载AR记录作为第二步。例如:

result = Product.search("test", load: false).response

# If you also need AR records, could do something like:
product_ids    = result.map(&:id)
products_by_id = {}

Product.where(id: product_ids).find_each do |ar_product|
  products_by_id[ar_product.id] = ar_product
end

merged_result = result.map do |es_product|
  es_product[:ar_product] = products_by_id[es_product.id]}
end

此外,检索存储在ES索引中的特定记录的文档可能会有所帮助,通常我可以通过在Product类中定义以下方法来做到这一点:

def es_document
  return nil unless doc = Product.search_index.retrieve(self).presence
  Hashie::Mash.new doc
end

答案 1 :(得分:1)

您可以使用select: truewith_hit方法将记录和搜索文档放在一起。例如:

result = Product.search("test", select: true)
products_with_total_prices =
  result.with_hit.map do |product, hit|
    {
      product: product,
      total_price: hit["_source"]["total_price"]
    }
  end