Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Elasticsearch: Use loop in Painless script

I have an old version of Elasticsearch (5.6.16) on a production environment that I can’t upgrade.

I’m trying to use a loop in a painless script_score script but I always face a runtime error.

All my documents can have one or several "badges", here the mapping:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

"myDocument":{
    "properties":{
        "badges":{
            "type":"nested",
            "properties":{
                "name":{
                    "type":"keyword"
                }
            }
        },
    }
},

My goal is to do a custom script that will provide a better score for documents with a specific type of badge

So I made this script

for (item in doc['badges']) {
    if (item['name'] == "myCustomBadge") {
        return _score * 10000;
    }
}
return _score;

But unfortunately, I’m getting errors while I try to use it

{
    "query":{
        "function_score":{
            "query":{
                "match_all": {}
            },
            "functions":[
                {
                    "script_score":{
                        "script":{
                            "inline":"for (item in doc['badges']) { if (item['name'] == \"myCustomBadge\") { return _score * 10000; }}return _score;",
                            "lang":"painless"
                        }
                    }
                },
            ]
        }
    }
}

    "error":{
        "root_cause":[
            {
                "type":"script_exception",
                "reason":"runtime error",
                "script_stack":[
                    "org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:77)",
                    "org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:36)",
                    "for (item in doc['badges']) { ",
                    " ^---- HERE"
                ],
                "script":"for (item in doc['badges']) { if (item['name'] == \"myCustomBadge\") { return _score * 10000; }}return _score;",
                "lang":"painless"
            }
        ],
        "type":"search_phase_execution_exception",
        "reason":"all shards failed"
    }


I tried to change the for with an other variant, but same error.

    for(int i = 0; i < doc['badges']; i++) {
        if (doc['badges'][i]['name'] == "uaWorker") {
            return _score * 10000;
        }
    }
    return _score;

Could you help me find what I did wrong?
Thanks you all

>Solution :

The problem is not the loop but the fact that badges is nested and you’re trying to access it from doc values. In this case, you need to access the array of badges from the _source document directly, like this:

for (item in params._source['badges'])
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading