如何使用点符号访问 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::Lazy
和 Enumerator#map
。将 ES 查询返回的每个值映射到 convert_to_object
函数,使每个条目成为一个完整的结构。
该代码非常通用,适用于我获得的每个索引。
我正在使用 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::Lazy
和 Enumerator#map
。将 ES 查询返回的每个值映射到 convert_to_object
函数,使每个条目成为一个完整的结构。
该代码非常通用,适用于我获得的每个索引。