如何在 elastic 5.x 上的 script_fields 处访问嵌套属性

bit*_*ter 9 elasticsearch

我需要为我的查询迭代无痛脚本字段上的嵌套对象,但符号 doc['nestedProperty.property'] 没有给我值,也没有使用数组符号 doc['nestedProperty.property'][0]

关于如何使用它的任何想法?

编辑

一个文档示例:

{
    "neestedProperty": [
      {
        "property": 12,
        "innerNeestedProperty": {
          "innerProperty1": 45,
          "innerProperty2": -45
        }
      }
    ]
}
Run Code Online (Sandbox Code Playgroud)

示例查询:

{
  "query": {
    match_all: {}
  },
  "script_fields": {
    "scripted": {
      "script": {
        "inline": "doc['neestedProperty.property'] * params.multiplier",
        "params": {
          "multiplier": 100
        },
        "lang": "painless"
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

Emi*_*ode 6

doc-notation显然不嵌套对象上的工作,但你可以直接访问_source的霍斯特Seirer指出-object。

复杂的是访问_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;
Run Code Online (Sandbox Code Playgroud)

即使您将源作为参数调用,也不必将其添加到参数列表中。

编辑

如果您需要从父文档的角度编写脚本(也许您需要组合多个嵌套文档),则上述内容很有用。

但是,有一个缺点是您只能使用原始源,这意味着未分析的字符串和只是字符串的日期等。

通常,通过包含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
              }
            }
          }
        }
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

此代码所做的只是单独查看每个嵌套文档(因为它们在内部存储为单独的文档),并在其上运行脚本。而这些(内部单独存储的)文档可以使用 doc-notation。

结果将为您提供原始文档,以及一个inner_hits包含每个嵌套文档及其来源的部分,以及一个脚本字段my_value

使用嵌套文档作为单独的条目可能只是感觉很奇怪,但仍然必须使用完整路径 ( nestedProperty.property)

并且您必须注意这样一个事实,即这个查询现在只返回其中包含嵌套文档的文档,而之前的代码将返回带有作为脚本字段的空数组的文档。但是,如果您想要所有文档,您可以使用带有match_all-clause的 bool-query 。

最后,我不知道这是否适用于 elastic 5(就像最初的问题一样),但我已经在 7.3 上进行了确认,并且根据文档,它也应该适用于例如 5.0。

我知道我迟到了,但也许我可以帮助其他人寻找相同的答案。


Hor*_*rer -1

_source对象实际上是一个LinkedHashMap(请参阅参考文档中有关无痛调试的章节。)因此,为了访问字段,您可以使用get方法。如果您需要通过参数动态选择文档字段,这会很方便。

选择字段的另一种方法是使用点语法:

ctx._source.some_field
Run Code Online (Sandbox Code Playgroud)

导航和选择文档字段时,您必须记住字段的数据类型。

对于您的特定情况,neestedProperty字段是您可以迭代的嵌套类型的列表(/ ArrayList )。该列表的元素的类型为LinkedHashMap

因此,对于您的示例,这将是:

ArrayList nestedObjects = ctx._source.get('neestedProperty'); 

for(o IN nestedObjects) { 
    o.get('property') = o.get('property')*params.multiplier; 
}
Run Code Online (Sandbox Code Playgroud)