ElasticSearch 多级父子聚合

我有一个父母/子女结构在3个层次。让我们说:

公司-> 雇员-> 上市时间

因为这里经常更新可用性(以及 Employee) ,所以我选择使用父/子结构来对抗嵌套。搜索功能工作正常(所有文档都在正确的碎片中)。

现在我要对这些结果进行分类。根据公司的元数据(第一级)对它们进行排序很容易。但我也需要排序的第三级(可用性)。

我想要按照以下方式分类的公司名单:

  • Distance from location given ASC
  • 等级 DESC
  • 最快可用 ASC

例如:

A 公司在5英里外,等级是4级,他们的员工最快在20小时内到达 B 公司也在5英里以外,也有4级,但最快他们的一个员工在5小时内可用。

因此排序结果需要是 B,A。

我希望为每个数据添加特殊的权重,因此我开始编写聚合,这些聚合稍后可以在我的 custom_ score 脚本中使用。

创建索引、导入数据和搜索的完整要点
现在,我已经设法编写了一个实际返回结果的查询,但是可用性聚合桶是空的。 但是,我也得到了结果太结构化,我想扁平他们。

现在我回来了:

公司 IDS-> 员工 IDS-> 第一次可用

我想有这样的聚合:

公司 IDS-> 第一次可用

这样我就能够做我的 custom_score脚本来计算分数和排序他们正确。

更简单的问题:
如何按多级(大级)子级排序/聚合并可能使结果变平。

3665 次浏览

您应该检查 R-Tree 数据结构 https://en.wikipedia.org/wiki/R-tree

你不需要聚合来做这些:

以下是分类标准:

  1. 距离 ASC (company.location)
  2. 评级 DESC (company.atings _ value)
  3. 最快的未来可用性 ASC (company.Employee.ailability.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 比较棘手,因为您需要查找每个公司最接近请求时间的可用性(公司 > 雇员 > 可用性) ,并使用该持续时间作为 第三排序标准。

我们将在孙子级别使用 function_score查询来获取请求时间和命中 _score中每个可用性之间的时间差。(然后我们将使用 _score作为第三个排序条件)。

为了达到这个目标,我们需要在 has_child查询中使用 has_child查询。

对于每个公司,我们都希望最快可用的员工(当然还有最近可用的员工)。弹性搜索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(这样我们就可以使用 最大倒数时间,直到每个员工可用,以及每个公司可用的 最大倒数员工可用)。

综上所述,我们继续查询 公司,但使用 公司 > 雇员 > 职位空缺生成 _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" }
}
}