0

I would like to create a scripted field that checks two properties of a nested field.

I have an ES index that contains information about processes. A process is configured as a nested object. Each doc can have more than one process. It is also possible to have more than one process of the same kind (same processDefinitionKey).

This is how the processes are structured at the moment:

"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"
    }
  }
}

Now I am interested in all active processes of a specific kind. So they must have a specific processDefinitionKey and must not have an ended property yet. I've written an ES query for it:

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

I have added this query as a filter that I can use on the Kibana dashboards. I think it works as it should.

However, I would prefer to add this property "has an active process of this kind" as a column in a search table by creating a scripted field for it. This is the scripted field I have come up with so far (in Painless):

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

But the results here do not align with the query above. I am afraid that this script checks whether there is a process with the correct processDefinitionKey and a process without the ended property. But it does not check whether both properties are true for the same process.

How can I make sure the scripted field checks both the processDefinitionKey and the ended property of the same process?

I use Kibana 6.4.2

EDIT:

Example of a document where the scripted field should return true (the service_agreement process has not ended yet, the other process has):

{
  "_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"
    ]
  }
}

Example of a document where the scripted field should return 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"
    ]
  }
}
NeleR
  • 43
  • 5

1 Answers1

1

Here you are dealing with nested documents. So you need to iterate over the nested docs and evaluate if the required condition is a match or not. This can be achieved using the following script:

UPDATED Answer:

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;

Script in single line:

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;

The scripted field will be of boolean type.

Hope this helps!

Nishant
  • 7,504
  • 1
  • 21
  • 34
  • Thanks @NishantSaini for your response! Due to the holiday time, I was not able to test this earlier. I'm sorry to say this does not return the desired output :( If I run `params._source.process` I get an array of processes. But I don't seem to be able to iterate over it (even `params._source.process.length` gives me nothing). I do not get any errors, so I am not sure what I'm doing wrong. – NeleR Jan 04 '19 at 09:13
  • @NeleR Its been a long time and I guess I have deleted my sample data as well. Will re-look and let you know. – Nishant Jan 04 '19 at 11:10
  • Still the same problem :( – NeleR Jan 07 '19 at 08:52
  • This time I have tested with the sample data that you provided. It's working fine for me – Nishant Jan 07 '19 at 10:59
  • Still not iterating over array?? – Nishant Jan 07 '19 at 11:46
  • 1
    @OpsterESNinjaNishant, you beautiful thing!! I had been trying to do something *very* similar for hours, and I kept getting errors because I was trying to access the fields with `doc['field']`. Changing to `params['_source']` did it for me. Nowhere in the awful ES documentation I have found that nested fields can't be accessed with `doc`. THANK YOU – undefinederror Dec 11 '20 at 16:17