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标准:

  1. 距离ASC(company.location)
  2. 评级DESC(company.rating_value)
  3. 最快的未来可用性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