Elasticsearch:在 Painless 脚本中使用循环

Elasticsearch: Use loop in Painless script

我在生产环境中有一个旧版本的 Elasticsearch (5.6.16),我无法升级。

我正在尝试在无痛 script_score 脚本中使用循环,但我总是遇到运行时错误。

我所有的文档都可以有一个或几个“徽章”,这里是映射:

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

我的目标是编写一个自定义脚本,为具有特定徽章类型的文档提供更好的分数

所以我做了这个脚本

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

但不幸的是,我在尝试使用它时遇到错误

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


我尝试用其他变体更改 for,但同样的错误。

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

你能帮我找出我做错了什么吗? 谢谢大家

问题不在于循环,而在于 badges 是嵌套的,而您正试图从文档值访问它。在这种情况下,您需要直接从 _source 文档访问徽章数组,如下所示:

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