使用ElasticSearch按给定数组排序

时间:2018-10-01 03:08:47

标签: elasticsearch elasticsearch-painless

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

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

我需要查询按日期分组但按这种权重排序的提要。我试图使用不费力的方法来创建排序功能,但是我仍然无法确定权重:

{
    "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给我一个靠近数组定义的编译错误。我的猜测是我无法定义JSON对象的列表/数组:

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

有没有排序脚本可以完成此操作吗?

1 个答案:

答案 0 :(得分:1)

无痛不是一种类似于javascript的语言。您不能只使用类似JSON的语法定义Array。

您可以获取阵列的完整文档here。 另外,您还有一个创建Map来表示您的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缓存脚本的编译版本,因为即使weights数组发生更改,源也将保持不变。