使用ScriptedMetricAggregationBuilder脚本访问Record内对象的ES问题
如何在ScriptedMetricAggregationBuilder脚本中访问嵌套对象字段
这个问题我之前也碰到过,核心原因是Elasticsearch脚本里doc和_source这两种上下文的访问逻辑有差异,咱们一步步来解决:
为什么doc.recordtwo.propertyone会报错?
doc上下文只能直接访问被单独索引到倒排索引中的顶级字段或扁平化后的字段。虽然你的映射里定义了recordtwo.propertyone,但它属于嵌套对象结构,doc上下文无法直接通过点路径的方式访问(除非用完整字段名的方括号语法,且该字段确实被索引了)。而doc.id能正常访问,是因为id是顶级字段,默认就会被索引到倒排索引里。
解决方案1:用_source访问(最稳妥)
_source保留了文档的原始结构,完全对应你定义的映射,所以直接用它来访问嵌套属性就不会有问题。示例代码如下:
ScriptedMetricAggregationBuilder myAgg = ScriptedMetricAggregationBuilder .scriptedMetric("nested_property_agg") .initScript(new Script("state.total = 0")) .mapScript(new Script("state.total += _source.recordtwo.propertyone")) .combineScript(new Script("return state.total")) .reduceScript(new Script("def finalTotal = 0; states.each { finalTotal += it }; return finalTotal"));
这里直接通过_source.recordtwo.propertyone就能拿到你要的属性值,逻辑和你预期的完全一致。
解决方案2:用doc上下文的正确语法(仅限字段已被索引)
如果你一定要用doc上下文,得用完整字段名的方括号语法,并且加上.value获取实际值:
// 脚本中的访问方式 doc['recordtwo.propertyone'].value
不过这种方式有局限性:如果recordtwo是nested类型(不是普通的object类型),doc上下文根本无法跨嵌套层访问,这时候还是得用_source或者配合nested聚合来处理。
额外提醒
- 要是你的
recordtwo是nested类型,那必须在nested聚合内部执行脚本,或者直接用_source访问,因为nested类型的文档是独立存储的,doc上下文没法直接穿透访问。 _source虽然会加载完整文档,性能比doc略差一点,但胜在可靠,能适配所有嵌套结构的访问场景,大多数情况下这点性能差异可以忽略。
内容的提问来源于stack exchange,提问作者Akash Gupta
相关产品推荐
相关产品推荐

