我需要在无痛的script_fields上为我的查询迭代嵌套对象,但是符号doc ['nestedProperty.property']没有给我这个值,也没有使用数组符号doc ['nestedProperty.property'] [0] < / p>
关于如何使用它的任何想法?
文档示例:
{
"neestedProperty": [
{
"property": 12,
"innerNeestedProperty": {
"innerProperty1": 45,
"innerProperty2": -45
}
}
]
}
示例查询:
{
"query": {
match_all: {}
},
"script_fields": {
"scripted": {
"script": {
"inline": "doc['neestedProperty.property'] * params.multiplier",
"params": {
"multiplier": 100
},
"lang": "painless"
}
}
}
}
答案 0 :(得分:2)
doc
标记显然不适用于嵌套对象,但是正如Horst Seirer指出的那样,您可以直接访问_source
对象。
复杂的是,访问_source
取决于脚本执行的上下文; ctx
变量并非始终可用。
对于scripted_fields
,您可以改用params._source
。但这在其他上下文(例如在查询部分)中将不可用
拥有_source
之后,可以使用get
或使用点符号来完成元素的访问,并且嵌套字段将是一个数组。因此,例如params._source.nestedProperty[0].property
将从第一个嵌套对象中获取值。
对于脚本字段,您应该返回一个对象,但是可以是一个数组。因此,在您的示例中,我将使用以下内容:
def returnval=[];
for (nested in params._source.nestedProperty) {
returnval.add(nested['property']*params.multiplier)
}
return returnval;
即使您将源称为参数,也不必将其添加到参数列表中。
如果您需要从父文档的角度编写脚本(也许需要合并多个嵌套文档),则上述内容很有用。
但是,有一个缺点,就是您只能使用原始数据源,这意味着未分析的字符串以及仅是字符串的日期等。
通常,通过在script_fields
部分中包含inner_hits
来直接使用嵌套文档中的脚本字段可能会容易得多。像这样:
{
"query": {
"nested": {
"path": "nestedProperty",
"query": {
"match_all": {}
},
"inner_hits": {
"_source": true,
"script_fields": {
"my_value": {
"script": {
"source": "doc['nestedProperty.property'].value*params.multiplier",
"params": {
"multiplier": 100
}
}
}
}
}
}
}
}
此代码的作用是单独查看每个嵌套文档(因为它们在内部存储为单独的文档),并在它们上运行脚本。这些(内部存储的单独文件)文档 可以使用文档符号。
结果将为您提供原始文档,以及一个inner_hits
部分,其中包含每个嵌套文档及其来源,以及一个脚本字段my_value
。
您可能会觉得奇怪,只是将嵌套文档用作单独的条目,而仍然必须使用完整路径(nestedProperty.property
)
您必须记住一个事实,即该查询现在仅返回具有嵌套文档的文档,而之前的代码将以脚本字段返回一个空数组的文档。但是,如果需要所有文档,则可以使用带有match_all
子句的布尔查询。
最后,我不知道这是否适用于弹性5(就像原始问题一样),但是我已经在7.3上得到确认,并且根据文档,它也应该适用于例如5.0。
我知道我来晚了,但是也许我可以帮助其他人寻找相同的答案。
答案 1 :(得分:0)
_source 对象实际上是 LinkedHashMap (请参阅参考文档中有关无痛调试的章节。)因此,为了访问字段,您可以使用< em> get 方法。如果您需要通过参数动态选择文档字段,这很方便。
选择字段的另一种方法是使用点语法:
ctx._source.some_field
在导航和选择文档字段时,您必须记住字段的数据类型。
对于您的特定情况, neestedProperty 字段是嵌套类型的列表(/ ArrayList ),您可以迭代它。此列表的元素的类型为 LinkedHashMap 。
因此,对于您的示例,这将是:
ArrayList nestedObjects = ctx._source.get('neestedProperty');
for(o IN nestedObjects) {
o.get('property') = o.get('property')*params.multiplier;
}
答案 2 :(得分:0)
实际上,我在 Discussion.elastic.co here...
上找到了解决方案GET my_index/_search
{
"script_fields": {
"new_scripted_field_name": {
"script": {
"source": "doc['nestedProperty.property'].value"
}
}
}
}
相反,@Emil波特的回答,您可以使用doc
,只是你必须使用点符号,而不是括号标记。
我使用Elasticsearch V7和discuss.elastic.co后使用Elasticsearch V6。