2

I am passing params map in the painless script, that map is type of <String, Long>. The key of the map defines the id and the value defines the foundDate in epoch Long.

The elastic Document have the raw structure like this :

doc:{
     [ "id":11406, // type:Long
      "lastFixed": 1666015888000 // type epoch millis
     ]  // ...mutiple ids and their lastFixed Dates
}

I have calculate the average difference between the foundDate and lastFixed (both are in epoch).

I have build the ES Painless script as below:

"script": {
              "source": "(doc['lastFixed'] - params[doc['id']] )/ (1000*60*60)",
              "lang": "expression",
              "params": {
                "11406": 1614084531000,
                "11473": 1073523856000,
                "11549": 1447461154000,
                "43904": 1666015887000,
                "43905": 1666015887000,
                "43906": 1666015887000,
                "43907": 1666015887000,
                "43908": 1666015888000,
                "43909": 1666015888000,
                "43910": 1666015888000
                }
            }

For nesting on the array of id & lastFound date I am using nest-path-aggr-name i.e. the nested path.

I want to pass the dynamic value in the params map as it will give the foundDate from the map for the same id in the Elasticsearch document.

But I am getting the parsing error from ES. I have tired with param.doc['id'] and param[] but both are falling and giving parsing error.

What is the correct way to pass the dynamic value in params map.

Rushikesh Sabde
  • 1,376
  • 1
  • 8
  • 24

2 Answers2

2

Below is based on my understanding of your issue

I have assumed below mapping for your document.

PUT index-name
{
  "mappings": {
    "properties": {
      "nested_field":{
        "type": "nested"
      }
    }
  }
}

In your question I believe nested_field is of type nested.

Sample Document

POST index-name/_doc
{
  "nested_field": [
    {
      "id": 11406,
      "lastFixed": 1666015888000
    },
    {
      "id": 11407,
      "lastFixed": 1666015888000
    }
  ]
}

I am using nested aggregation to access nested fields.

Query

{
  "size":0,
  "aggs": {
    "nest-path-aggr-name": {
      "nested": {
        "path": "nested_field"
      },
      "aggs": {
        "average_agg": {
          "avg": {
            "script": {
              "source": """
                    for(entry in params.entrySet())
                    {
                      if (entry.getKey() == doc['nested_field.id'].value.toString())
                      {
                        return ( doc['nested_field.lastFixed'].value -  entry.getValue())/ (1000*60*60); 
                      }
                    }
                      return 0;
                  """,
              "params": {
                "11406": 1614084531000,
                "11473": 1073523856000,
                "11549": 1447461154000,
                "43904": 1666015887000,
                "43905": 1666015887000,
                "43906": 1666015887000,
                "43907": 1666015887000,
                "43908": 1666015888000,
                "43909": 1666015888000,
                "43910": 1666015888000
              }
            }
          }
        }
      }
    }
  }
}
jaspreet chahal
  • 8,817
  • 2
  • 11
  • 29
  • Actually I wanted to pass the dynamic value in the params map to fetch the respective value. the dynamic value for the params key will be fetched from Elasticsearch document. – Rushikesh Sabde Oct 19 '22 at 09:04
  • @RushikeshSabde are you referring to these values "11406": 1614084531000, "11473": 1073523856000, "11549": 1447461154000,"43904": 1666015887000, "43905": 1666015887000, "43906": 1666015887000, "43907": 1666015887000, "43908": 1666015888000, "43909": 1666015888000, "43910": 1666015888000 ?. You will only pass key and value will be from field in another document. So you want to join two document, find difference and get average of it. Am I getting it right? – jaspreet chahal Oct 19 '22 at 09:14
  • 2
    This answer helped me to solve a similar issue with passing an arbitrary map of id-timestamp values – Anatoly Yakimchuk Jan 12 '23 at 12:20
0

I was just trying to solve this problem too. If I understand you correctly, you would like to use a value returned from the document as the "key" for the hash you have created in params. I think the params.get() function might be what you are looking for.

I also changed the script language to "painless". This shouldn't cause any conflicts with the code, but it does enable the two functions that I used.

Here is the link to the Elasticsearch example that uses params.get(): https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting-using.html#script-shorten-syntax

I lost the documentation for int.toString(), but I tested it and it works as expected.

"script": {
              "source": "(doc['lastFixed'] - params.get(doc['id'].toString()))/ (1000*60*60)",
              "lang": "painless",
              "params": {
                "11406": 1614084531000,
                "11473": 1073523856000,
                "11549": 1447461154000,
                "43904": 1666015887000,
                "43905": 1666015887000,
                "43906": 1666015887000,
                "43907": 1666015887000,
                "43908": 1666015888000,
                "43909": 1666015888000,
                "43910": 1666015888000
                }
            }
galdron
  • 1
  • 1