赞
踩
作者:后端小肥肠
创作不易,未经允许严禁转载。
目录
3.4.1. 将面要素wkt转换为GeoPoint类型的数组
在处理千万级图斑叠加分析时,传统的后端GIS工具,如Geotools和PostGIS,往往难以满足实时性和高效性的要求。在这一挑战背景下,引入Elasticsearch作为空间叠加查询的解决方案,成为了一种创新且高效的选择。本文将探讨如何利用Java和Elasticsearch实现GIS中的千万级图斑叠加分析,以项目场景为基础,通过对传统后端GIS工具与Elasticsearch的性能比较,旨在为读者展示Elasticsearch作为一种新兴的空间数据处理工具的价值和潜力,为解决类似问题的开发者提供新的思路和解决方案。
本文适合有Elasticsearch和GIS后台编程基础的jym,如本文对你有帮助和启示,请三连支持一下小肥肠~
假设叠加分析的场景为求一个面要素下包含的点要素,点要素图层有1000万个点,要求在短时间内返回叠加分析结果。以后端为JAVA的背景下,常用的叠加分析方案有Geotools,Postgis,ES,目前将从技术方案特点,性能,优缺点,以及处理千万级图斑的可行性这几个方面依次介绍这几种技术方案。
技术方案特点:
性能评估:
优缺点:
处理千万级图斑的可行性:
依赖 | 版本 |
---|---|
Spring Boot | 2.6.3 |
Java | 1.8以上 |
Elasticsearch | 7.9.3 |
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
- </dependency>
- <dependency>
- <groupId>org.locationtech.jts</groupId>
- <artifactId>jts-core</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
- </dependencies>
基于工具将点要素图层导入Elasticsearch,这里怎么导入的不细讲,相关资料可自行百度:
注意看Shape字段类型要如上图才能支持面包含点类型的叠加分析。
- {
- "code": 200,
- "status": "success",
- "message": "OK",
- "data": {
- "list": [
- {
- "name": "地类名称",
- "code": "地类编码",
- "count": 178,
- "hectares": 541213,
- "ares": 3243,
- "squareMetres": 32432
- }
- ]
- }
- }
由返回结构可看出,我们需要返回点要素的name,code和面积属性(平方米,公亩,公顷)。
- private List<GeoPoint> parseWKTGeometry(String wkt) {
- List<GeoPoint> points = new ArrayList<>();
- GeometryFactory geometryFactory = new GeometryFactory();
- WKTReader reader = new WKTReader(geometryFactory);
-
- try {
- Geometry geometry = reader.read(wkt);
- if (geometry instanceof Polygon) {
- Polygon polygon = (Polygon) geometry;
- LinearRing ring = (LinearRing) polygon.getExteriorRing();
- Coordinate[] coordinates = ring.getCoordinates();
- for (Coordinate coord : coordinates) {
- double lat = coord.y;
- double lon = coord.x;
- points.add(new GeoPoint(lat, lon));
- }
- }
- } catch (ParseException e) {
- e.printStackTrace();
- }
-
- return points;
- }
- public ResponseStructure overlayAnalysis(OverlayDTO overlayDTO) {
- try {
- if(StringUtils.isEmpty(overlayDTO.getGeometry())){
- return ResponseStructure.failed("空间范围不可为空");
- }
- String geometry=overlayDTO.getGeometry();
- // 1. 指定检索 Index
- SearchRequest request = new SearchRequest();
- request.indices(ALIAS);
-
- // 2. 指定检索方式
- SearchSourceBuilder builder = new SearchSourceBuilder();
-
- // 3. 解析 WKT 格式的多边形
- List<GeoPoint> points = parseWKTGeometry(geometry);
-
- // geoPolygonQuery 代表着的是多边形查询
- builder.query(QueryBuilders.geoPolygonQuery("Shape", points)).trackTotalHits(true).size(0);
-
- // 4. 添加聚合查询
- TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("code").field(FIELD_CODE)
- .subAggregation(AggregationBuilders.sum("MJ").field("YJJBNTMJ")).size(500);
- builder.aggregation(termsAggregationBuilder);
-
- request.source(builder);
-
- // 5. 执行查询
- SearchResponse resp = restHighLevelClient.search(request, RequestOptions.DEFAULT);
-
- // 6.1 输出总数
- long total = resp.getHits().getTotalHits().value;
-
- // 6.2 聚合结果
- List<DataVo> lists = new ArrayList<>();
- Terms terms = resp.getAggregations().get("code");
- List<? extends Terms.Bucket> buckets = terms.getBuckets();
- for (Terms.Bucket bucket : buckets) {
- // 获取分组总面积
- Sum mj = bucket.getAggregations().get("MJ");
- Double sum = mj.getValue();
- log.info("面积:{}", sum);
-
- // 获取代码
- String code = bucket.getKeyAsString();
- log.info("代码:{}", code);
- QuickStatistics quickStatistics = quickStatisticsMapper.selectOne(new LambdaQueryWrapper<QuickStatistics>()
- .eq(QuickStatistics::getCode, code).eq(QuickStatistics::getType, FIELD_CODE));
-
- // 如果大数据库查到的代码没有在 pg 库的数据字典中,忽略不统计
- if (quickStatistics == null) {
- log.info("未统计的代码:{}", code);
- continue;
- }
-
- String name = quickStatistics.getName();
- lists.add(new DataVo(name, code, bucket.getDocCount(), sum, sum / 100, sum / 10000));
- }
-
- JBNTVO jbntvo = new JBNTVO(lists);
- return ResponseStructure.success(jbntvo);
- } catch (Exception e) {
- log.error(e.getMessage(), e);
- return ResponseStructure.failed("叠加分析异常");
- }
- }
上述方法使用Elasticsearch进行查询,根据指定的几何图形执行地理多边形查询,并添加聚合查询以计算特定区域内的指标数据。最后,它将查询结果进行处理,包括统计各个区域的指标数据和计算相关指标,然后封装成特定的VO对象返回。如果在执行过程中出现异常,则记录错误信息并返回相应的错误响应。
由上图可知,只需要输入叠加面要素的wkt格式数据,便可在短时间内拿到叠加分析结果。
本文以千万级图斑叠加分析为背景,首先对比了常规技术栈和ES的优缺点,最后以实际代码讲解了如何基于ES实现千万级图斑叠加分析,如有更好的想法欢迎在评论区留言进行讨论~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。