当前位置: 首页 > wzjs >正文

公司要求做网站营销策划方案案例

公司要求做网站,营销策划方案案例,有内涵大气的公司名字,莆田外贸建站在地图类应用中,当需要展示大量地理兴趣点时,直接将所有点渲染在地图上会导致视觉混乱,影响用户体验。为此,我基于 Elasticsearch 提供的 geotile_grid 和 geo_bounding_box 查询能力,实现了一套高效的 POI 聚合展示方…

在地图类应用中,当需要展示大量地理兴趣点时,直接将所有点渲染在地图上会导致视觉混乱,影响用户体验。为此,我基于 Elasticsearch 提供的 geotile_gridgeo_bounding_box 查询能力,实现了一套高效的 POI 聚合展示方案。

🧩 问题背景:POI 数量巨大,直接渲染效率低

在地图类应用中,我们常常需要展示大量的地理兴趣点(Point of Interest, POI),例如商圈、门店、用户位置等。然而,当 POI 数量达到数万甚至数十万级别时,若将所有点一次性加载并渲染在地图上,不仅会导致页面卡顿、交互延迟,还会因标记重叠严重而降低用户体验。更严重的问题包括:

  • 前端性能瓶颈:大量 DOM 节点或图形元素导致浏览器渲染压力剧增;
  • 视觉混乱:点与点之间相互遮挡,信息难以辨识;
  • 无差别展示:无法根据地图缩放层级动态调整展示粒度;
    在这里插入图片描述
    因此,我们需要一种既能减少前端渲染压力,又能保留关键信息的地图聚合方案。

🛠️ 技术方案:基于 Elasticsearch 的 geotile_grid 聚合机制

本方案基于 Elasticsearch 的 geotile_gridgeo_bounding_box 查询能力,结合球面几何算法,实现了poi高效聚合与展示。整个流程如下:

  1. 获取地图视口范围:通过左上角和右下角坐标限定查询范围;
  2. 映射地图缩放层级到 precision,根据当前地图 zoom level 动态计算合适的 geotile_grid 聚合精度;
  3. 提取聚合点并计算代表点,对每个 tile 内最多 100 个点进行球面几何中位数计算,得出一个最具代表性的点用于展示。

流程图:
在这里插入图片描述
效果展示:

Screen-2025-07-03-163545

📌 地图聚合的核心:geotile_grid

在本方案中,我们使用了 Elasticsearch 的 geotile_grid 聚合方式来实现地图兴趣点的分区聚合。
geotile_grid 本质上是一种基于 Geohash 编码的空间划分机制。它将整个地图视图划分为多个大小一致的矩形区域(称为 tile),每个 tile 包含落在其范围内的所有 POI。

  • tile 的粒度由 precision 控制:precision 越高,tile 越小,聚合越精细;
  • 结合 zoom level 动态映射 precision:根据当前地图缩放层级,动态设置合适的精度值,使聚合结果与地图展示粒度保持一致;
  • 支持子聚合操作:我们可以在每个 tile 中嵌套 top_hits 聚合,获取最多 100 个原始点用于后续中心点计算;

通过这种方式,我们可以:

  • 高效筛选出当前地图视口内的所有 tile;
  • 快速获取每个 tile 内的 POI 数据;
  • 为每个 tile 计算出最具代表性的“中心点”,用于前端展示;
  • 这不仅显著提升了后端查询效率,也为前端提供了结构清晰、层次分明的地图聚合展示能力。

🧑‍💻 示例代码片段

核心代码:基于 geotile_grid 实现地图点聚合

// 1. 构建筛选条件(仅保留地理范围查询)
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
queryBuilder.must(QueryBuilders.geoBoundingBoxQuery("latLng").setCorners(new GeoPoint(topLeftLat, topLeftLon), new GeoPoint(bottomRightLat, bottomRightLon)));// 2. 构建 geotile_grid 聚合
GeoGridAggregationBuilder geoTileGridAgg = AggregationBuilders.geotileGrid("grid_agg").field("latLng").precision(15); // 可根据缩放级别动态设置 precision// 3. 添加子聚合 top_hits(获取每个 tile 内的 latLng 坐标)
TopHitsAggregationBuilder topHitsAgg = AggregationBuilders.topHits("top_hits_agg").fetchSource("latLng", null).size(100);
geoTileGridAgg.subAggregation(topHitsAgg);// 4. 构建最终查询
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(queryBuilder).withAggregations(geoTileGridAgg).withMaxResults(0) // 不需要返回实际文档.build();// 5. 执行查询并解析聚合结果
SearchHits<ShopESEntity> searchHits = elasticsearchRestTemplate.search(searchQuery, ShopESEntity.class);// 6. 解析聚合结果并生成展示点
List<DisplayPointVO> displayPoints = new ArrayList<>();
if (searchHits.hasAggregations()) {List<? extends MultiBucketsAggregation.Bucket> buckets = getBuckets(searchHits.getAggregations(), "grid_agg");for (MultiBucketsAggregation.Bucket bucket : buckets) {List<MapUtils.Poi> poiList = getPoiList(bucket); // 获取该 tile 内最多 100 个点MapUtils.Poi meanPoi = MapUtils.computeSphericalMean(poiList); // 计算球面几何中位点if (meanPoi != null) {DisplayPointVO vo = new DisplayPointVO();vo.setCount(bucket.getDocCount());vo.setLat(meanPoi.getLat());vo.setLng(meanPoi.getLng());displayPoints.add(vo);}}
}

最终DSL如下:

{"size": 0,"aggs": {"poi_agg": {"geotile_grid": {"field": "latLng","precision": 29},"aggs": {"points": {"top_hits": {"size": 100,"_source": {"includes": ["latLng"]}}}}}},"query": {"geo_bounding_box": {"latLng": {"top_left": {"lat": 30.293813,"lon": 120.10432},"bottom_right": {"lat": 30.167403,"lon": 120.217002}}}}
}

球面几何中位数算法(简化版)

public static class MapUtils {public static class Poi {private final double lat;private final double lon;public Poi(double lat, double lon) {this.lat = lat;this.lon = lon;}public double getLat() { return lat; }public double getLng() { return lon; }}public static Poi computeSphericalMean(List<Poi> poiList) {if (poiList.isEmpty()) return null;double sumX = 0, sumY = 0, sumZ = 0;for (Poi p : poiList) {double latRad = Math.toRadians(p.lat);double lonRad = Math.toRadians(p.lon);sumX += Math.cos(latRad) * Math.cos(lonRad);sumY += Math.cos(latRad) * Math.sin(lonRad);sumZ += Math.sin(latRad);}int n = poiList.size();double avgX = sumX / n;double avgY = sumY / n;double avgZ = sumZ / n;double hyp = Math.sqrt(avgX * avgX + avgY * avgY);double latAvg = Math.toDegrees(Math.atan2(avgZ, hyp));double lngAvg = Math.toDegrees(Math.atan2(avgY, avgX));return new Poi(latAvg, lngAvg);}
}
http://www.dtcms.com/wzjs/348397.html

相关文章:

  • 有哪些可以在网上做兼职的网站网站怎样优化seo
  • 闲置服务器做网站挣钱百度关键词搜索引擎排名优化
  • 模板网站与定制网站的优缺点宁德市区哪里好玩
  • 网站建设总流程图广告投放是什么工作
  • 做俄语网站建设广州品牌营销策划公司排名
  • 网站做301打不开广州十大营销策划公司
  • 安徽省工程建设信息网职称查询搜索引擎网站推广如何优化
  • 网站关键词怎样修改网站排行榜前十名
  • 站长工具 怎么做网站地图太原seo推广外包
  • 网页界面设计实训报告湘潭seo优化
  • 麻城建设局网站停办行业数据统计网站
  • 珠海网站建设找哪家好免费查权重工具
  • 饮食网站首页页面搜索广告排名
  • 可以做go分析的网站西安百度关键词优化排名
  • 在wordpress上添加播放器网站优化方案
  • 字体怎么下载到wordpress北京网站sem、seo
  • 网站设计尺寸百度模拟搜索点击软件
  • 电商网站如何做seo网络广告推广方法
  • 天水做网站互动营销的案例及分析
  • 霍邱网站建设web设计一个简单网页
  • 公司网站建设前期方案有哪些平台可以做推广
  • seo好wordpress主题百度seo是什么意思呢
  • 深圳网站推广外包百度seo什么意思
  • 社区网站如何做精准信息300099
  • wordpress彩色标签插件seo网络营销案例分析
  • 做设计用的素材下载网站百度站长工具
  • 电脑系统做的好的网站好最近几天的新闻大事
  • 设计网站用什么语言惠州seo优化
  • 营销型企业网站建设板块设置百度手机关键词排名工具
  • 绵阳做手机网站建设懂得网站推广