使用 ElasticSearch 按给定数组排序

With ElasticSearch sort by given array

我在 ElasticRearch 中存储了一系列提要。每个提要都有发布此类提要的演员和发布日期。在另一个地方,我以这种方式为每个演员存储一个加权值:

weights: [{'id': 'mark', 'weight': 1}, {'id': 'jane', 'weight': 3}]

我需要查询按日期分组但按此类权重排序的提要。我尝试使用 painless 制作排序功能,但我坚持定义权重:

{
    "size": 0,
    "query": {
        "bool": {
            "should": [
                {
                    "bool": {
                        "must": [
                            {
                                "term": {
                                    "actor.id": "mark"
                                }
                            },
                            {
                                "range": {
                                    "published": {"gte": "2017-09-30T15:37:21.530483"}
                                }
                            }
                        ]
                    }
                },
                {
                    "bool": {
                        "must": [
                            {
                                "term": {
                                    "actor.id": "jane"
                                }
                            },
                            {
                                "range": {
                                    "published": {"gte": "2017-09-30T15:37:21.530483"}
                                }
                            }
                        ]
                    }
                }
            ]
        }
    },
    "aggs": {
        "dates": {
            "terms": {
                "field": "published_date",
            },
            "aggs": {
                "top_verbs_hits": {
                    "top_hits": {
                        "sort": {
                            "_script": {
                                "type": "number",
                                "script": {
                                    "lang": "painless",
                                    "source": "def weights = [{'id': 'mark', 'weight': 1}, {'id': 'jane', 'weight': 3}]; def weight = 0; for (int i = 0; i < weights.length; ++i) { if (weights[i].id == doc.actor.id) return weights[i].weight; } return weight;"
                                },
                                "order": "asc"
                            }
                        },
                        "_source": {
                            "includes": ["published", "actor", "object", "target", "extra"]
                        },
                        "size": 100
                    }
                }
            }
        }
    },
    "sort": [
        {
            "published": {
                "order": "desc"
            }
        }
    ],
}

为清楚起见,无痛功能如下:

def weights = [{'id': 'mark', 'weight': 1}, {'id': 'jane', 'weight': 3}]; 
def weight = 0; 
for (int i = 0; i < weights.length; ++i) 
{ 
    if (weights[i].id == doc.actor.id) 
    return weights[i].weight; 
} 
return weight;

Elastic 在数组定义附近给我一个编译错误。我的猜测是我无法定义 list/array 个 JSON 个对象:

compile error","script_stack":["def weights = [{'id': 'mark', 'weight ...","               ^---- HERE"]....

是否有任何方法可以使用或不使用排序脚本来完成此操作?

Painless 不是 javascript 类语言。您不能只使用类似 JSON 的语法定义数组。

您可以获得阵列的完整文档 here。 您还有一个创建地图来表示您的 JSON 对象。

但在您的情况下,您应该明确使用 scripts params

你能试试这样的东西吗:

"sort": {
    "_script": {
        "type": "number",
        "script": {
            "lang": "painless",
            "source": "def weight = 0; for (int i = 0; i < params.weights.length; ++i) { if (params.weights[i].id == doc['actor.id'].value) return params.weights[i].weight; } return weight;"
            "params": {
              "weights" :[{'id': 'mark', 'weight': 1}, {'id': 'jane', 'weight': 3}]
            } 
        },
        "order": "asc"
    }
}

通过使用参数,您可以使用 JSON 语法定义您的条目数据,而且您还允许 elasticsearch 缓存脚本的编译版本,因为即使权重数组发生变化,源代码也将保持不变.