how to check for key exist in elastic-search painless parameters? - elasticsearch

How to check for key exists in painless script map parameters.
In below query check a.toString() key exist in params
I've tried everything but didn't get it to work.
Please help me
mapping :
"id": {
"type": "long"
}
query:
{
"query":{
"bool":{
"filter":[
{
"script": {
"script": {
"lang": "painless",
"params": {
"29232":2541,
"minDistance": 0
},
"source": "def a=doc['id'].getValue();double distance=params[a.toString()]; return distance <= 1000 && distance >= params['minDistance']"
}
}
}
]
}
}
}

The params is just a Java Map object. So, the following checks if the key exists in the params and exits early with a false if it does not exist.
GET test/_search
{
"query":{
"bool":{
"filter":[
{
"script": {
"script": {
"lang": "painless",
"params": {
"29232":2541,
"minDistance": 0
},
"source": """
def a=doc['id'].getValue();
if (!params.containsKey(a.toString())) {
return false;
}
double distance=params[a.toString()];
return distance <= 1000 && distance >= params['minDistance']
"""
}
}
}
]
}
}
}

Related

Elasticsearch conditional sorting by different fields (some fields can be empty)

I have objects like this:
{
subStatus: {
updatedAt: 3
},
statusUpdatedAt: 1
},
{
subStatus: null,
statusUpdatedAt: 2
}
I need to sort the objects conditionally as follows:
relative to the subStatus.updatedAt field if the subStatus field exists,
or relative to the statusUpdatedAt field if the subStatus field does not exist
If both fields are absent, objects should be sorted to the end of the list
I used the following query:
"sort": {
"_script": {
"type": "number",
"order": "asc",
"script": {
"lang": "painless",
"source": "if(doc['subStatus'].value != null) { return doc['subStatus.updatedAt'].value } else { return doc['statusUpdatedAt'].value }"
}
}
}
But I get an Error: "No field found for [subStatus] in mapping with types []"
Could you advise me how to solve the problem?
Try check by "size".
POST idx_fields/_bulk
{"index":{}}
{"subStatus": { "updatedAt": 3 }, "statusUpdatedAt": 1 }
{"index":{}}
{"subStatus": null, "statusUpdatedAt": 2 }
GET idx_fields/_search
{
"sort": {
"_script": {
"type": "number",
"order": "asc",
"script": {
"lang": "painless",
"source": "if(doc['subStatus.updatedAt'].size() > 0) { return doc['subStatus.updatedAt'].value } else { return doc['statusUpdatedAt'].value }"
}
}
}
}

How to compare field with _id in elasticsearch script?

{
"query":{
"bool":{
"must":{
"match_all":{
}
},
"filter":[
{
"script":{
"source":"doc['id'].value == doc['_id'].value",
"lang":"painless"
}
}
]
}
},
"track_total_hits":true
}
So doc['_id'].value is the line that causing error. How should i compare field value with _id value?
In normal documents "_id" is string and "id" is long, but i broke a few and now in them both are strings, how could I find them?
I think your id field type is keyword, so; you can't call doc['id'].value without .keyword.
try this:
"script": {
"script": {
"source": "doc['id.keyword'].value == doc['_id'].value",
"lang": "painless"
}
}

How to subtract two values in Elasticsearch

I'm trying to get the difference between two fields. I'm using Elasticsearch 5.5.
I have already tried
{
"query": {
"bool": {
"filter": {
"script": {
"script": "doc['students.total_fee'].value - doc['students.paid_fee'].value"
}
}
}
}
}
but it is returning empty "hits".
I have also tried
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "students",
"query": {
"script": {
"script": {
"inline": "doc['students.total_fee'].value - doc['students.paid_fee'].value",
"lang": "expression"
}
}
}
}
}
]
}
}
and it is returning "0".
also the "script_fields" did not worked.
{ "script_fields" :
{ "difference" :
{ "script" : "doc['students.total_fee'].value - doc['students.paid_fee'].value"
} } }
suppose I have data in following format.
"_source" : {
"students" : [
{
"name" : "A",
"total_fee" : 12345,
"paid_fee" : 12344.8
},
{
"name" : "B",
"total_fee" : 23456,
"paid_fee" : 23455.6
}
]
}
Now I want to get the difference between "total_fee" and "paid_fee" for each student.
I expect to get an array of differences for all students.
Thanks in advance :D
You need to use the below query and my es version is 6.2.2. It is giving a perfect result. But remember scripting is generally CPU intensive.
If you normal field then below query working fine.
{
"size": 10,
"script_fields": {
"fare_diff": {
"script": "doc[\"students.total_fee\"].value - doc[\"students.paid_fee\"].value"
}
}
}
If you are using a nested field parameter then the query would be like below.
{
"script_fields": {
"fare_diff": {
"script": {
"lang": "painless",
"source": "int total = 0; def l = new ArrayList(); for (int i = 0; i < params['_source']['students'].size(); ++i) { l.add(params['_source']['students'][i]['total_fee'] - params['_source']['students'][i]['paid_fee']);} return l.toArray();"
}
}
}
}
Reason: Because nested documents are indexed as separate documents, they can only be accessed within the scope of the nested query, the nested/reverse_nested aggregations, or nested inner hits.

query by time difference beetween dates in elasticsearch

Say I have index like this:
{"id": "12345678", "start": 1541999620214, "end": 1541999620222 }
How do I query for documents with end-start > 10? and now-start < 60000
Simply like this:
{
"query": {
"script": {
"script": {
"source": "doc.end.value - doc.start.value < 10"
}
}
}
}
and
{
"query": {
"script": {
"script": {
"source": "System.currentTimeMillis() - doc.start.value < 60000"
}
}
}
}
As a performance optimization, though, you could store the end - start information inside your document at indexing time so you don't have to resort to scripting and your query would simply become:
{
"query": {
"range": {
"diff": {
"lt": 10
}
}
}
}

ElasticSearch Script Fields accessable in sort

Is it possible to access a script_field inside a sort?
I have
search_body["script_fields"] = {
"test": {
"script": {
"lang": "painless",
"inline": skill_rating_algorithm.replace("\n", ""),
"params" : {
"param1": {....}
}
}
}
}
And as sort:
search_body["sort"] = {
"_script": {
"type": "string",
"order": "desc",
"script": {
"lang": "painless",
"inline": "def c = params._fields['test']; return c;",
}
},
"number_of_years_of_experience": {"order": "desc"},
"value.raw": {"order": "asc"},
}
But this only return errors.
I could do a sorting script but i need the value returned in the document as a separate key.
My questions is:
Can i access the script_field "test" inside the sort? (More script_fields will come and i will need different ordering)

Resources