作者:后端小肥肠
创作不易,未经允许严禁转载。
目录
1. 前言
2. 叠加分析场景方案对比
2.1. Geotools
2.2. PostGIS
2.3. Elasticsearch
3. 基于ElastcSearch实现叠加分析代码实践
3.1. 开发环境搭建
3.1.1. 所需版本和工具
3.1.2. pom依赖
3.2. 数据导入
3.3. 返回结构设计
3.4. 核心代码讲解
3.4.1. 将面要素wkt转换为GeoPoint类型的数组
3.4.2. 编写叠加分析方法函数
3.5. 结果测试
4. 结语
1. 前言
在处理千万级图斑叠加分析时,传统的后端GIS工具,如Geotools和PostGIS,往往难以满足实时性和高效性的要求。在这一挑战背景下,引入Elasticsearch作为空间叠加查询的解决方案,成为了一种创新且高效的选择。本文将探讨如何利用Java和Elasticsearch实现GIS中的千万级图斑叠加分析,以项目场景为基础,通过对传统后端GIS工具与Elasticsearch的性能比较,旨在为读者展示Elasticsearch作为一种新兴的空间数据处理工具的价值和潜力,为解决类似问题的开发者提供新的思路和解决方案。
本文适合有Elasticsearch和GIS后台编程基础的jym,如本文对你有帮助和启示,请三连支持一下小肥肠~
2. 叠加分析场景方案对比
假设叠加分析的场景为求一个面要素下包含的点要素,点要素图层有1000万个点,要求在短时间内返回叠加分析结果。以后端为JAVA的背景下,常用的叠加分析方案有Geotools,Postgis,ES,目前将从技术方案特点,性能,优缺点,以及处理千万级图斑的可行性这几个方面依次介绍这几种技术方案。
2.1. Geotools
- 技术方案特点: Geotools是一个开源的Java GIS工具库,提供了丰富的地理信息处理功能。
- 性能评估: 在处理大规模空间数据时,Geotools可能性能较差,因其设计更偏向于灵活性和功能的全面性,而不是针对大规模数据的优化。
- 优缺点: Geotools拥有丰富的功能和灵活的定制性,但在处理千万级图斑等大规模数据时,可能表现不佳。
- 处理千万级图斑的可行性:在处理大规模数据时可能性能较差,可能需要额外的优化和资源才能满足实时性和高效性的要求。
2.2. PostGIS
- 技术方案特点: PostGIS是一个基于PostgreSQL的空间数据库扩展,提供了丰富的空间分析功能。
- 性能评估: PostGIS在处理大规模空间数据时性能较好,可以通过索引和优化查询来提高处理效率。
- 优缺点: PostGIS具有成熟的空间数据处理功能和优秀的性能,但在某些情况下可能需要额外的硬件资源来支持高负载。
- 处理千万级图斑的可行性:PostGIS在处理大规模数据时性能较好,通过适当的索引和优化查询可以有效提高处理效率,但要在短时间内完千万级图斑成叠加分析可能存在一些限制,特别是在复杂的叠加条件或者硬件资源受限的情况下。
2.3. Elasticsearch
-
技术方案特点:
- 分布式实时搜索与分析引擎: Elasticsearch是一个基于分布式架构的实时搜索和分析引擎,专注于快速、实时的数据处理和查询。
- 地理空间支持: Elasticsearch通过地理空间索引和查询功能,能够有效地处理地理空间数据,包括点、线、面等要素。
- 高度可扩展性: Elasticsearch具有良好的横向扩展能力,能够轻松地处理大规模数据,因此适合处理千万级图斑等大规模空间数据。
-
性能评估:
- 实时性和高效性: Elasticsearch在处理大规模数据时表现出色,具有较快的响应速度和高效的查询性能,能够满足实时性和高效性的要求。
- 水平扩展性: 通过横向扩展集群节点,Elasticsearch能够有效地处理大规模数据,保持良好的性能表现。
-
优缺点:
- 优点:
- 实时性高:Elasticsearch支持实时索引和查询,能够快速处理最新的空间数据。
- 强大的查询功能:Elasticsearch提供丰富的查询语法和功能,能够灵活地满足各种空间分析需求。
- 可扩展性强:Elasticsearch具有良好的横向扩展能力,能够轻松地处理大规模数据。
- 缺点:
- 学习曲线较陡:对于新手来说,可能需要一定时间来学习Elasticsearch的数据模型和查询语法。
- 硬件资源需求较高:在处理大规模数据时,可能需要较多的硬件资源来支持高负载的查询请求。
- 优点:
-
处理千万级图斑的可行性:
- 可行性: Elasticsearch在处理大规模数据时表现优异,尤其擅长于实时性和高效性要求较高的场景,因此对于处理千万级图斑是可行的选择。通过合适的索引设计和优化查询,Elasticsearch能够有效地处理千万级图斑数据,并提供快速准确的查询结果。
3. 基于ElastcSearch实现叠加分析代码实践
3.1. 开发环境搭建
3.1.1. 所需版本和工具
依赖 | 版本 |
---|---|
Spring Boot | 2.6.3 |
Java | 1.8以上 |
Elasticsearch | 7.9.3 |
3.1.2. pom依赖
<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>
3.2. 数据导入
基于工具将点要素图层导入Elasticsearch,这里怎么导入的不细讲,相关资料可自行百度:
注意看Shape字段类型要如上图才能支持面包含点类型的叠加分析。
3.3. 返回结构设计
{
"code": 200,
"status": "success",
"message": "OK",
"data": {
"list": [
{
"name": "地类名称",
"code": "地类编码",
"count": 178,
"hectares": 541213,
"ares": 3243,
"squareMetres": 32432
}
]
}
}
由返回结构可看出,我们需要返回点要素的name,code和面积属性(平方米,公亩,公顷)。
3.4. 核心代码讲解
3.4.1. 将面要素wkt转换为GeoPoint类型的数组
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;
}
3.4.2. 编写叠加分析方法函数
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对象返回。如果在执行过程中出现异常,则记录错误信息并返回相应的错误响应。
3.5. 结果测试
由上图可知,只需要输入叠加面要素的wkt格式数据,便可在短时间内拿到叠加分析结果。
4. 结语
本文以千万级图斑叠加分析为背景,首先对比了常规技术栈和ES的优缺点,最后以实际代码讲解了如何基于ES实现千万级图斑叠加分析,如有更好的想法欢迎在评论区留言进行讨论~