Elasticsearch Java API 针对 Geohash7 网点进行分桶聚合

需求整理:

geohash 7网格存储工作热度和学习热度数值,支持随机区域多个范围的热度聚合;

创建索引结构

索引文档需要包含 Geohash 网格、工作热度和学习热度等字段。可以在 Elasticsearch 中定义一个索引,确保 location 字段的类型是 geo_point,用于支持地理空间查询。

PUT /geohash_index
{
  "mappings": {
    "properties": {
      "geohash": {
        "type": "keyword"
      },
      "location": {
        "type": "geo_point"
      },
      "work_heat": {
        "type": "integer"
      },
      "study_heat": {
        "type": "integer"
      }
    }
  }
}

插入数据

POST /geohash_index/_doc/1
{
  "geohash": "wx4g0f0",
  "location": {
    "lat": 39.9042,
    "lon": 116.4074
  },
  "work_heat": 100,
  "study_heat": 50
}

聚合查询

使用 Elasticsearch 的地理空间范围聚合 (geo_distance aggregation) 实现不同范围内的数据聚合,比如 500m、1.5km、3km,统计工作热度和学习热度。

import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.range.GeoDistanceAggregationBuilder;
import org.elasticsearch.common.unit.DistanceUnit;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;

public class GeoAggregationQuery {

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    public void searchWithGeoAggregation() {
        // 构建地理空间范围聚合
        GeoDistanceAggregationBuilder geoDistanceAgg = AggregationBuilders.geoDistance("geo_distance_agg", new GeoPoint(39.9042, 116.4074))
                .unit(DistanceUnit.METERS)
                .field("location")
                .addRange(0, 500)     // 0-500米范围
                .addRange(500, 1500)  // 500米-1.5公里范围
                .addRange(1500, 3000) // 1.5公里-3公里范围
                .subAggregation(AggregationBuilders.sum("total_work_heat").field("work_heat"))   
                .subAggregation(AggregationBuilders.sum("total_study_heat").field("study_heat")); 

        // 构建查询
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.matchAllQuery())  
                .addAggregation(geoDistanceAgg)
                .build();

        elasticsearchRestTemplate.search(searchQuery, YourEntityClass.class)
                .getAggregations()
                .asMap()
                .forEach((name, agg) -> {
                    // 处理聚合结果,例如输出各个范围内的热度总和
                    System.out.println(name + ": " + agg);
                });
    }
}

可以根据需求扩展查询条件,例如增加 BoolQueryBuilder 来过滤特定条件的数据。同样可以通过修改距离和单位,调整聚合的范围。

额外:怎么评估最外围擦边的点要不要算在里面

1. 中心点与半径
每个距离范围(如 500m、1.5km、3km)是以你指定的中心点为原点,计算的半径距离。在执行查询时,Elasticsearch 通过 Haversine 公式(或其他地理距离计算方法)确定每个文档的地理位置是否在某个距离范围内。
2. 文档是否落入某个范围
• 如果文档的地理位置计算出的距离小于或等于给定范围(例如 500m 或 1.5km),那么这个文档会被算作属于这个距离范围的桶。
• 如果文档的地理位置超过了给定的范围,那么它不会算作在该桶中。

具体实现

  1. 基于中心点:计算距离的起点是你定义的中心点,所有距离测量都是围绕这个点进行。
  2. 严格的边界计算:擦边的点如果距离与给定范围正好相等,它会被算作属于该范围。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值