【问题标题】:Combine nested fields in scripted field在脚本字段中组合嵌套字段
【发布时间】:2018-12-19 12:14:51
【问题描述】:

我想创建一个脚本字段来检查嵌套字段的两个属性。

我有一个 ES 索引,其中包含有关进程的信息。一个进程被配置为一个嵌套对象。每个 doc 可以有多个进程。也可以有多个相同类型的进程(相同的processDefinitionKey)。

目前流程的结构如下:

"process" : {
  "type" : "nested",
  "include_in_parent" : true,
  "properties" : {
    "created" : {
      "type" : "date",
      "format" : "date_optional_time"
    },
    "ended" : {
      "type" : "date",
      "format" : "date_optional_time"
    },
    "id" : {
      "type" : "text",
      "index" : false
    },
    "processDefinitionKey" : {
      "type" : "keyword"
    },
    "processDefinitionName" : {
      "type" : "text",
      "fields" : {
        "raw" : {
          "type" : "keyword",
          "index" : false
        }
      },
      "analyzer" : "case_insensitive_sort"
    }
  }
}

现在我对特定类型的所有活动进程感兴趣。所以他们必须有一个特定的processDefinitionKey 并且必须有一个ended 属性。我已经为它写了一个 ES 查询:

{
  "query": {
    "nested": {
      "path": "process",
      "query": {
        "bool": {
          "must": {
            "match": {
              "process.processDefinitionKey": "service_agreement"
            }
          },
          "must_not": {
            "exists": {
              "field": "process.ended"
            }
          }
        }
      }
    }
  }
}

我已将此查询添加为可在 Kibana 仪表板上使用的过滤器。我认为它可以正常工作。

但是,我希望通过为它创建一个脚本化字段,将此属性“具有此类活动进程”添加为搜索表中的一列。这是迄今为止我提出的脚本字段(在 Painless 中):

doc['process.processDefinitionKey'].contains('service_agreement') && doc['process.ended'].empty

但是这里的结果与上面的查询不一致。恐怕这个脚本会检查是否存在具有正确processDefinitionKeya 进程和没有ended 属性的a 进程。但它不会检查这两个属性对于同一进程是否为真。

如何确保脚本化字段同时检查同一进程的 processDefinitionKeyended 属性?

我使用 Kibana 6.4.2

编辑:

脚本字段应返回true的文档示例(service_agreement 进程尚未结束,其他进程已结束):

{
  "_index": ...,
  "_type"...,
  "_id": ...,
  "_version": ...,
  "_score": ...,
  "_source": {
    "type": ...,
    ...,
    "process": [
      {
        "id": "130707",
        "created": "2017-09-11T09:50:52.000+02:00",
        "ended": "2017-09-13T10:16:43.000+02:00",
        "processDefinitionKey": "so_ondertekenproces",
        "processDefinitionName": "Samenwerkingsovereenkomst",
        "incidents": []
      },
      {
        "id": "c2a83c07-15f7-11e7-a20e-0242ac120004",
        "created": "2017-03-31T11:52:32.000+02:00",
        "processDefinitionKey": "service_agreement",
        "processDefinitionName": "Service Agreement",
        "incidents": []
      }
    ]
  },
  "fields": {
    "process.created": [
      "2017-03-31T09:52:32.000Z",
      "2017-09-11T07:50:52.000Z"
    ],
    "process.ended": [
      "2017-09-13T08:16:43.000Z"
    ]
  }
}

脚本字段应返回false的文档示例:

{
  "_index": ...,
  "_type": ...,
  "_id": ...,
  "_score": ...,
  "_source": {
    "type": ...,
    ...,
    "process": [
      {
        "id": "17154",
        "created": "2017-05-24T13:21:40.000+02:00",
        "ended": "2017-05-24T13:23:24.000+02:00",
        "processDefinitionKey": "so_ondertekenproces",
        "processDefinitionName": "Samenwerkingsovereenkomst",
        "incidents": []
      },
      {
        "id": "17263",
        "created": "2017-05-24T13:23:29.000+02:00",
        "ended": "2017-09-27T14:31:00.000+02:00",
        "processDefinitionKey": "so_ondertekenproces",
        "processDefinitionName": "Samenwerkingsovereenkomst",
        "incidents": []
      },
      {
        "id": "f1cd056e-15f7-11e7-a20e-0242ac120004",
        "created": "2017-03-31T11:53:51.000+02:00",
        "ended": "2017-10-10T11:35:47.000+02:00",
        "processDefinitionKey": "service_agreement",
        "processDefinitionName": "Service Agreement",
        "incidents": []
      }
    ]
  },
  "fields": {
    "process.created": [
      "2017-03-31T09:53:51.000Z",
      "2017-05-24T11:21:40.000Z",
      "2017-05-24T11:23:29.000Z"
    ],
    "process.ended": [
      "2017-05-24T11:23:24.000Z",
      "2017-09-27T12:31:00.000Z",
      "2017-10-10T09:35:47.000Z"
    ]
  }
}

【问题讨论】:

  • 我的回答有用吗?

标签: nested elasticsearch-painless kibana-6


【解决方案1】:

在这里您正在处理嵌套文档。因此,您需要遍历嵌套文档并评估所需条件是否匹配。这可以使用以下脚本来实现:

更新答案:

boolean res = false;
for(int i = 0; i < params['_source']['process'].length; i++) {
   if(params['_source']['process'][i]['processDefinitionKey'] == 'service_agreement' && !params['_source']['process'][i].containsKey('ended')) {
      res = true;
      break;
   }
}
return res;

单行脚本:

boolean res = false; for(int i = 0; i < params['_source']['process'].length; i++){ if(params['_source']['process'][i]['processDefinitionKey'] == 'service_agreement' && !params['_source']['process'][i].containsKey('ended')) { res = true; break; }} return res;

脚本字段将是boolean 类型。

希望这会有所帮助!

【讨论】:

  • 感谢@NishantSaini 的回复!由于假期时间,我无法更早地进行测试。很抱歉,这不会返回所需的输出:(如果我运行params._source.process,我会得到一系列进程。但我似乎无法迭代它(即使params._source.process.length 什么也没给我) . 我没有收到任何错误,所以我不确定我做错了什么。
  • @NeleR 已经很久了,我想我也删除了我的示例数据。将重新查看并通知您。
  • 还是同样的问题:(
  • 这次我用你提供的样本数据进行了测试。对我来说效果很好
  • @OpsterESNinjaNishant,你这个漂亮的东西!!几个小时以来,我一直在尝试做一些非常类似的事情,但由于我试图使用doc['field'] 访问这些字段,所以一直出错。更改为 params['_source'] 为我做了这件事。在糟糕的 ES 文档中,我发现无法使用 doc 访问嵌套字段。谢谢你
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-30
相关资源
最近更新 更多