在脚本字段中合并嵌套字段

时间:2018-12-19 12:14:52

标签: nested elasticsearch-painless kibana-6

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

我有一个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仪表板上使用的过滤器。我认为它可以正常工作。

但是,我希望通过为此属性创建一个脚本字段,将该属性“具有此类活动过程”添加为搜索表中的一列。到目前为止,这是我提出的脚本化字段(无痛):

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

但是这里的结果与上面的查询不一致。恐怕此脚本会检查是否存在具有正确processDefinitionKey a 进程和没有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"
    ]
  }
}

1 个答案:

答案 0 :(得分:0)

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

更新后的答案:

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类型。

希望这会有所帮助!