我有3个级别的父/子结构。让我们说:
公司 - >员工 - >可用性
由于此处经常更新可用性(以及员工),因此我选择使用父/子结构来嵌套。搜索功能正常(所有文档都在正确的分片中)。
现在我想对这些结果进行排序。通过公司(第1级)的元数据对它们进行排序很容易。但我需要按第3级(可用性)排序。
我想要按以下方式排序的公司列表:
例如:
A公司距离酒店5英里,评级为4,其中一名员工可在20小时内完成 公司B也在5英里外,也有4级,但最快的一名员工可在5小时内完成。
因此排序结果必须是B,A。
我想对每个数据添加特别的权重,所以我开始编写聚合,以后可以在我的custom_score脚本中使用。
Full gist for creating index, importing data and searching
现在,我设法写了一个实际返回结果的查询,但是可用性聚合桶是空的。
但是,我也得到了过于结构化的结果,我想将它们弄平。
目前我回来了:
公司IDS - >员工IDS - >第一次可用性
我希望聚合如下:
公司IDS - >第一次可用性
通过这种方式,我可以使用custom_score
脚本来计算分数并对其进行正确排序。
更简化的问题:
如何对多级(大)孩子进行排序/聚合,并可能使结果变平。
答案 0 :(得分:3)
您不需要汇总来执行此操作:
这些是排序标准:
如果忽略#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
查询。
对于每家公司,我们都希望拥有最快的员工(当然还有他们最接近的可用性)。对于这样的案例,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
以用作#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" }
}
}
答案 1 :(得分:-1)
您应该查看R-Tree数据结构https://en.wikipedia.org/wiki/R-tree。