ElasticSearch多层次的父子聚合
我有一个3级的父母/孩子结构。 我们说:
公司 – >员工 – >可用性
由于可用性(也是员工)在这里经常更新,我select使用父/子结构对嵌套。 而searchfunction正常工作(所有文件在正确的碎片)。
现在我想sorting这些结果。 通过来自公司(第一级)的元数据进行sorting非常简单。 但是我还需要按第三级(可用性)进行sorting。
我想要按以下sorting的公司列表:
- 距离ASC的位置
- 评级DESC
- 最快的可用性ASC
例如:
A公司距离5英里,评级为4,最快的员工在20小时内可用,B公司也在5英里以外,也有4个等级,但最快的员工在5个小时内可用。
所以sorting结果需要是B,A
我想为每个数据添加特殊的权重,所以我开始编写可以在我的custom_score脚本中使用的聚合。
完整的要点,用于创build索引,导入数据和search
现在,我设法写了一个实际返回结果的查询,但可用性聚合桶是空的。 但是,我也得到的结果太结构化,我想扁平化他们。
目前我回来了:
公司IDS – >员工IDS – >第一个可用性
我想要聚合像:
公司IDS – >第一可用性
这样我就可以做我的custom_score
脚本来计算分数并正确地sorting它们。
更简化的问题:
如何sorting/聚合多层次(盛大)的孩子,并可能使结果变平。
你不需要聚合来做到这一点:
这些是sorting标准:
- 距离ASC(company.location)
- 评级DESC(company.rating_value)
- 最快的未来可用性ASC(company.employee.availability.start)
如果你忽略#3,那么你可以像这样运行一个相对简单的公司查询:
GET /companies/company/_search { "query": { "match_all" : {} }, "sort": { "_script": { "params": { "lat": 51.5186, "lon": -0.1347 }, "lang": "groovy", "type": "number", "order": "asc", "script": "doc['location'].distanceInMiles(lat,lon)" }, "rating_value": { "order": "desc" } } }
#3是棘手的,因为你需要find最接近请求时间的每个公司的可用性( 公司>员工>可用性 ),并使用该持续时间作为第三个分类标准。
我们打算在孙级使用一个function_score
查询来获取请求时间和命中_score
中的每个可用性之间的时间差。 (然后我们将使用_score
作为第三个sorting标准)。
为了到达孙辈,我们需要在has_child
查询中使用has_child
查询。
对于每个公司,我们都希望最快的员工(当然也是最接近的可用性)。 Elasticsearch 2.0将为我们提供一个"score_mode": "min"
,但是现在,由于我们只限于"score_mode": "max"
我们会让孙子的_score
成为时间的倒数 。
"function_score": { "filter": { "range": { "start": { "gt": "2014-12-22T10:34:18+01:00" } } }, "functions": [ { "script_score": { "lang": "groovy", "params": { "requested": "2014-12-22T10:34:18+01:00", "millisPerHour": 3600000 }, "script": "1 / ((doc['availability.start'].value - new DateTime(requested).getMillis()) / millisPerHour)" } } ] }
因此,现在每个孙子( 可用性 )的_score
将是1 / number-of-hours-until-available
(这样我们可以使用最大互惠时间,直到每个员工可用,并且每个公司可用的最大互惠(ly?) )。
_score
,我们继续查询公司,但使用公司>员工>可用性生成_score
作为#3分类标准使用:
GET /companies/company/_search { "query": { "has_child" : { "type" : "employee", "score_mode" : "max", "query": { "has_child" : { "type" : "availability", "score_mode" : "max", "query": { "function_score": { "filter": { "range": { "start": { "gt": "2014-12-22T10:34:18+01:00" } } }, "functions": [ { "script_score": { "lang": "groovy", "params": { "requested": "2014-12-22T10:34:18+01:00", "millisPerHour": 3600000 }, "script": "1/((doc['availability.start'].value - new DateTime(requested).getMillis()) / millisPerHour)" } } ] } } } } } }, "sort": { "_script": { "params": { "lat": 51.5186, "lon": -0.1347 }, "lang": "groovy", "type": "number", "order": "asc", "script": "doc['location'].distanceInMiles(lat,lon)" }, "rating_value": { "order": "desc" }, "_score": { "order": "asc" } } }
你应该检查出R-Tree数据结构https://en.wikipedia.org/wiki/R-tree 。