Elasticsearch附近API:聚合去重后geo_distance排序及查询生效问题
问题解答
1. 如何对聚合后的记录按geo_distance排序?
当前你的terms聚合默认按companyKey的文档数量排序,要实现聚合结果按每个公司最近分支的距离排序,需要在duplicateCount聚合下新增一个子聚合计算每个公司的最小距离,再基于该值排序。
修改后的查询代码如下:
const query = { query: { bool: { must: [ customQuery, { term: { "schedule.isShopOpen": true } }, { term: { isBranchAvailable: true } }, { term: { branchStatus: "active" } }, { match: { shopStatus: "active" } }, { script: { script: { params: { lat: parseFloat(req.lat), lon: parseFloat(req.lon) }, source: "doc['location'].arcDistance(params.lat, params.lon) / 1000 <= doc['searchRadius'].value", lang: "painless" } } } ] } }, aggs: { duplicateCount: { terms: { field: "companyKey", size: 10000, // 基于min_distance聚合值升序排序 order: { "min_distance": "asc" } }, aggs: { // 新增:计算每个公司下所有符合条件分支的最小距离 min_distance: { min: { script: { params: { lat: parseFloat(req.lat), lon: parseFloat(req.lon) }, source: "doc['location'].arcDistance(params.lat, params.lon)/1000" } } }, duplicateDocuments: { top_hits: { sort: [ { _geo_distance: { location: { lat: parseFloat(req.lat), lon: parseFloat(req.lon) }, order: "asc", unit: "km", mode: "min", distance_type: "arc", ignore_unmapped: true } } ], script_fields: { distance: { script: { params: { lat: parseFloat(req.lat), lon: parseFloat(req.lon) }, inline: "doc['location'].arcDistance(params.lat, params.lon)/1000" } } }, stored_fields: ["_source"], size: 1 } } } } } };
逻辑说明:
min_distance子聚合会计算每个公司下所有符合条件分支的最小距离值- 在
terms聚合的order参数中指定按min_distance升序排列,这样聚合后的公司就会按最近分支的距离从近到远排序
2. 查询操作(match、script等)是否会作用于聚合数据?
会的。Elasticsearch的执行流程是:
- 先执行
query部分的所有匹配条件(包括match、term、script筛选),得到符合要求的文档集合 - 再基于这个筛选后的集合执行后续的聚合操作
也就是说,你的聚合只会处理通过了bool.must中所有条件的文档,不会包含不符合条件的记录。比如你脚本中筛选的“在商家搜索半径范围内”的条件,会先过滤掉超出范围的分支,之后的companyKey聚合只会基于剩下的有效分支进行分组去重。
内容的提问来源于stack exchange,提问作者zulqarnain
相关产品推荐
相关产品推荐

