如何使用点符号访问 Chewy 结果?

How to access Chewy results with the dot notation?

我正在使用 Toptal's Chewy gem 连接和查询我的 Elasticsearch,就像 ODM 一样。

我正在使用 Chewy 以及 Elasticsearch 6,Ruby Rails 5.2 和 Active Record。

我已经这样定义了我的索引:

class OrdersIndex < Chewy::Index
  define_type Order.includes(:customer) do

    field :id, type: "keyword"

    field :customer do
      field :id, type: "keyword"
      field :name, type: "text"
      field :email, type: "keyword"
    end
  end
end

还有我的模特:

class Order < ApplicationRecord
  belongs_to :customer
end

这里的问题是,当我使用 Chewy 执行任何查询时,客户数据被反序列化为散列而不是对象,我无法使用点表示法访问嵌套数据。

results = OrdersIndex.query(query_string: { query: "test" })
results.first.id
# => "594d8e8b2cc640bb78bd115ae644637a1cc84dd460be6f69"

results.first.customer.name
# => NoMethodError: undefined method `name' for #<Hash:0x000000000931d928>

results.first.customer["name"]
# => "Frederique Schaefer"

如何使用点符号 (result.customer.name) 访问嵌套关联?或者反序列化对象(例如 Struct)中的嵌套数据,这允许我使用点表示法?

尝试使用

results = OrdersIndex.query(query_string: { query: "test" }).objects

它将查询结果转换为活动记录对象。所以点符号应该工作。如果您想加载与上述结果的任何额外关联,您可以在 Index 上使用 .load 方法。

如果您想将现有的 ES 嵌套对象转换为可使用点符号访问,请尝试参考此答案。 Open Struct 是在 ruby.

中完成任务的最佳方式

Unable to use dot syntax for ruby hash

还有,this一个人也能帮忙

如果您需要 openStruct 为嵌套对象工作,请参阅 this link

将刚刚反序列化的结果转换为 JSON 字符串并使用 OpenStruct 将其再次反序列化为 object_class 可能不是一个好主意,并且会产生很大的 CPU 成本。

我用不同的方式解决了它,使用递归和 Ruby 的原生 Struct,保留了 Chewy gem.

的惰性
def convert_to_object(keys, values)
  schema = Struct.new(*keys.map(&:to_sym))
  object = schema.new(*values)

  object.each_pair do |key, value|
    if value.is_a?(Hash)
      object.send("#{key}=", convert_to_object(value.keys, value.values))
    end
  end

  object
end

OrdersIndex.query(query_string: { query: "test" }).lazy.map do |item|
  convert_to_object(item.attributes.keys, item.attributes.values)
end

convert_to_object 获取一组键和另一个值,并从中创建一个结构。每当值数组项之一的 class 是哈希时,它就会递归地转换为结构,传递哈希键和值。

为了展现懒惰,这是 Chewy 最酷的部分,我使用了 Enumerator::LazyEnumerator#map。将 ES 查询返回的每个值映射到 convert_to_object 函数,使每个条目成为一个完整的结构。

该代码非常通用,适用于我获得的每个索引。