如何在弹性5.x

时间:2016-12-22 03:10:30

标签: elasticsearch

我需要在无痛的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"
      }
    }
  }
}

3 个答案:

答案 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。