问题描述
我有不同地点的商店索引。对于每家商店,我都有一个嵌套的折扣券列表。
现在我有查询以获取按给定位置最近的适用优惠券的距离排序的半径 x 公里内所有独特优惠券的列表
数据库 :: Elasticsearch
索引映射::
{
"mappings": {
"car_stores": {
"properties": {
"location": {
"type": "geo_point"
},"discount_coupons": {
"type": "nested","properties": {
"name": {
"type": "keyword"
}
}
}
}
}
}
}
示例文档::
{
"_index": "stores","_type": "car_stores","_id": "1258c81d-b6f2-400f-a448-bd728f524b55","_score": 1.0,"_source": {
"location": {
"lat": 36.053757,"lon": 139.525482
},"discount_coupons": [
{
"name": "c1"
},{
"name": "c2"
}
]
}
}
在给定位置的 x 公里区域内获取唯一折扣优惠券名称的旧查询 ::
{
"size": 0,"query": {
"bool": {
"must": {
"match_all": {}
},"filter": {
"geo_distance": {
"distance": "100km","location": {
"lat": 40,"lon": -70
}
}
}
}
},"aggs": {
"coupon": {
"nested": {
"path": "discount_coupons"
},"aggs": {
"name": {
"terms": {
"field": "discount_coupons.name","order": {
"_key": "asc"
},"size": 200
}
}
}
}
}
}
更新回复::
{
"took": 60,"timed_out": false,"_shards": {
"total": 3,"successful": 3,"skipped": 0,"Failed": 0
},"hits": {
"total": 245328,"max_score": 0.0,"hits": []
},"aggregations": {
"coupon": {
"doc_count": 657442,"name": {
"doc_count_error_upper_bound": -1,"sum_other_doc_count": 641189,"buckets": [
{
"key": "local20210211","doc_count": 1611,"back_to_base": {
"doc_count": 1611,"distance_script": {
"value": 160.61034409639765
}
}
},{
"key": "local20210117","doc_count": 1621,"back_to_base": {
"doc_count": 1621,"distance_script": {
"value": 77.51459886447356
}
}
},{
"key": "local20201220","doc_count": 1622,"back_to_base": {
"doc_count": 1622,"distance_script": {
"value": 84.15734462544432
}
}
},{
"key": "kisekae1","doc_count": 1626,"back_to_base": {
"doc_count": 1626,"distance_script": {
"value": 88.23770888201268
}
}
},{
"key": "local20210206","distance_script": {
"value": 86.78376012847237
}
}
},{
"key": "local20210106","doc_count": 1628,"back_to_base": {
"doc_count": 1628,"distance_script": {
"value": 384.12156408078397
}
}
},{
"key": "local20210113","distance_script": {
"value": 153.61681676703674
}
}
},{
"key": "local20","doc_count": 1629,"back_to_base": {
"doc_count": 1629,"distance_script": {
"value": 168.74132991524073
}
}
},{
"key": "local20210213","doc_count": 1630,"back_to_base": {
"doc_count": 1630,"distance_script": {
"value": 155.8335679860034
}
}
},{
"key": "local20210208","doc_count": 1632,"back_to_base": {
"doc_count": 1632,"distance_script": {
"value": 99.58790590445102
}
}
}
]
}
}
}
}
现在上面的查询将返回按计数排序的前 200 张优惠券默认值,但我想返回根据给定位置的距离排序的优惠券,即最接近的优惠券应该先出现。
有没有办法根据父键对嵌套聚合进行排序,或者我可以使用不同的数据模型解决这个用例吗?
更新查询::
{
"size": 0,"query": {
"bool": {
"filter": [
{
"geo_distance": {
"distance": "100km","location": {
"lat": 35.699104,"lon": 139.825211
}
}
},{
"nested": {
"path": "discount_coupons","query": {
"bool": {
"filter": {
"exists": {
"field": "discount_coupons"
}
}
}
}
}
}
]
}
},"order": {
"back_to_base": "asc"
},"size": 10
},"aggs": {
"back_to_base": {
"reverse_nested": {},"aggs": {
"distance_script": {
"min": {
"script": {
"source": "doc['location'].arcdistance(35.699104,139.825211)"
}
}
}
}
}
}
}
}
}
}
}
解决方法
有趣的问题。您始终可以通过数字子聚合的结果 order 一个 terms
聚合。这里的技巧是使用脚本通过 reverse_nested
aggregation 和 calculate the distance 从枢轴中转义嵌套上下文:
{
"size": 0,"query": {
"bool": {
"must": {
"match_all": {}
},"filter": {
"geo_distance": {
"distance": "100km","location": {
"lat": 40,"lon": -70
}
}
}
}
},"aggs": {
"coupon": {
"nested": {
"path": "discount_coupons"
},"aggs": {
"name": {
"terms": {
"field": "discount_coupons.name","order": {
"back_to_base": "asc"
},"size": 200
},"aggs": {
"back_to_base": {
"reverse_nested": {},"aggs": {
"distance_script": {
"min": {
"script": {
"source": "doc['location'].arcDistance(40,-70)"
}
}
}
}
}
}
}
}
}
}
}