简体   繁体   English

如何根据 elasticsearch 中的父文档字段对嵌套聚合字段进行排序?

[英]How to sort nested aggregation field based on parent document field in elasticsearch?

I have index of stores at various location.我有不同位置的商店索引。 With each store I have a nested list of discount coupon.对于每家商店,我都有一个嵌套的折扣券列表。

Now I have query to get list of all unique coupons in ax km of radius sorted by the distance of the nearest applicable coupon on given location现在我有查询以获取半径为 ax km 的所有唯一优惠券的列表,按给定位置上最近适用优惠券的距离排序

Database:: Elasticsearch数据库:: Elasticsearch

Index Mapping::索引映射::

{
"mappings": {
    "car_stores": {
        "properties": {
            "location": {
                "type": "geo_point"
            },
            "discount_coupons": {
                "type": "nested",
                "properties": {
                    "name": {
                        "type": "keyword"
                    }
                }
            }
        }
    }
}
}

Sample Doc::样本文件::

{
"_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"
        }
    ]
}
}

Old Query to get unique discount coupon names in x km area for given location::旧查询以获取给定位置 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
                }
            }
        }
    }
}
}

Updated Response::更新回复::

{
"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",
                    "doc_count": 1626,
                    "back_to_base": {
                        "doc_count": 1626,
                        "distance_script": {
                            "value": 86.78376012847237
                        }
                    }
                },
                {
                    "key": "local20210106",
                    "doc_count": 1628,
                    "back_to_base": {
                        "doc_count": 1628,
                        "distance_script": {
                            "value": 384.12156408078397
                        }
                    }
                },
                {
                    "key": "local20210113",
                    "doc_count": 1628,
                    "back_to_base": {
                        "doc_count": 1628,
                        "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
                        }
                    }
                }
            ]
        }
    }
}
}

Now the above query will return first 200 discount coupon default sorted by count but I want to return coupons sorted on distance based to given location ie the coupon that is nearest applicable should come first.现在上面的查询将返回按计数排序的前 200 张折扣优惠券默认值,但我想返回根据给定位置的距离排序的优惠券,即最近适用的优惠券应该排在第一位。

Is there any way to sort nested aggregations based on a parent key or can I solve this use case using a different data model?有没有办法根据父键对嵌套聚合进行排序,或者我可以使用不同的数据 model 来解决这个用例吗?

Update Query::更新查询::

{
"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"
                                }
                            }
                        }
                    }
                }
            }
        ]
    }
},
"aggs": {
    "coupon": {
        "nested": {
            "path": "discount_coupons"
        },
        "aggs": {
            "name": {
                "terms": {
                    "field": "discount_coupons.name",
                    "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)"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
}

Interesting question.有趣的问题。 You can always order a terms aggregation by the result of a numeric sub-aggregation.您始终可以根据数字子聚合的结果对terms聚合进行排序 The trick here is to escape the nested context via a reverse_nested aggregation and then calculate the distance from the pivot using a script:这里的技巧是通过reverse_nested聚合来逃避嵌套上下文,然后使用脚本计算与 pivot 的距离

{
  "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)"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 嵌套字段上的ElasticSearch聚合,父ID上有存储分区 - ElasticSearch Aggregation on nested field with bucketing on parent id 是否可以在父聚合定义的字段上执行Elasticsearch嵌套统计信息聚合? - Is it possible to perform elasticsearch nested stats aggregation on a field defined by the parent aggregation? 具有访问父字段的子聚合的嵌套聚合Elasticsearch - nested aggregation elasticsearch with access parent field for sub-aggregation 如何比较 elasticsearch 中的父字段与子聚合? - How to compare parent field with child aggregation in elasticsearch? 如何根据elasticsearch中嵌套字段的最小值对结果集进行排序? - How to sort the result set based on the minimum value of a nested field in elasticsearch? ElasticSearch - 通过嵌套字段上的嵌套聚合对聚合进行排序 - ElasticSearch - Ordering aggregation by nested aggregation on nested field 没有嵌套字段的elasticsearch不同的父子聚合 - elasticsearch distinct parent sub aggregation without nested field 嵌套(非数组)字段上的Elasticsearch聚合 - Elasticsearch aggregation on nested (not array) field Elasticsearch - 术语聚合嵌套字段 - Elasticsearch - Terms Aggregation nested field ElasticSearch - 如何使用字段别名进行嵌套字段聚合? - ElasticSearch - How can I do nested field aggregation with field aliases?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM