Elasticsearch地理空间之geo_shape

这篇具有很好参考价值的文章主要介绍了Elasticsearch地理空间之geo_shape。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

参考文章:

Elasticsearch地理形状
Elasticsearch geo_shape地理形状
ES地理范围查询第二讲:地理位置信息之geo_shape
ES GEO地理空间查询java版
Elasticsearch geo_point/geo_shape

一、概述

通常情况,我们使用一个经纬度坐标表示一个店铺的位置、一个用户的位置,经纬度在地图上仅仅表示一个点,有时候需要表示一个区域,例如:停车场、商场、学校等等,这些区域拥有各种各样的形状,包括:圆形、多边形等等。

ES中存储地理形状的数据类型为: geo_shape

geo_shape支持存储的常用形状数据如下:

  • 点(point)
  • 圆形(circle)
  • 矩形(envelope)
  • 多边形 (polygon)

提示: 在geo_shape中,点作为一种特殊的形状,geo_shape可以存储一个点。

二、geo_shape数据格式

geo_shape支持GeoJsonWKT(Well-Known Text)格式存储空间形状数据。建议使用wkt。详细支持的格式描述如下面图片上描述。
Elasticsearch地理空间之geo_shape

格式说明

  • GeoJson格式数据
    GeoJson格式参考官方网站:https://geojson.org/
    在es中则只需要存储其geometry的属性值即为geo_shape的值。
{
  "type": "Feature",
  "geometry": {
    "type": "Point",
    "coordinates": [125.6, 10.1]
  },
  "properties": {
    "name": "Dinagat Islands"
  }
}
  • wkt Well-Known Text (WKT)
POINT (-77.03653 38.897676) 
LINESTRING (-77.03653 38.897676,-77.009051 38.889939) 
POLYGON ((100.0 0.0, 101.0 0.0, 101.0 1.0, 100.0 1.0, 100.0 0.0)) 
MULTIPOINT (102.0 2.0, 103.0 2.0) 
MULTILINESTRING ((102.0 2.0, 103.0 2.0, 103.0 3.0, 102.0 3.0),(100.2 0.2, 100.8 0.2, 100.8 0.8, 100.2 0.8)) 
MULTIPOLYGON (((102.0 2.0, 103.0 2.0, 103.0 3.0, 102.0 3.0, 102.0 2.0)), ((100.0 0.0, 101.0 0.0, 101.0 1.0, 100.0 1.0, 100.0 0.0), (100.2 0.2, 100.8 0.2, 100.8 0.8, 100.2 0.8, 100.2 0.2))) 
GEOMETRYCOLLECTION (POINT (100.0 0.0), LINESTRING (101.0 0.0, 102.0 1.0)) 
BBOX (100.0, 102.0, 2.0, 0.0)

存储示例

  1. 定义geo_shape类型映射
PUT /example
{
    "mappings": {
        "properties": {
            "location": {
                "type": "geo_shape" // 定义location字段类型为geo_shape
            }
        }
    }
}
  1. 存储一个点
POST /example/_doc
{
    "location" : {
        "type" : "point", // 存储的图形类型为:point,表示存储一个坐标点
        "coordinates" : [-77.03653, 38.897676] // 坐标点格式: [经度, 纬度]
    }
}

POST /example/_doc
{
    "location" : "POINT (-77.03653 38.897676)"
}

  1. 存储一个多边形
POST /example/_doc
{
  "location": {
    "type": "polygon", // 存储的图形类型为: polygon,表示一个多边形
    "coordinates": [ // 支持多个多边形
      [ // 第一个多边形,多边形由下面的坐标数组组成。
        [100, 0], // 第一个坐标点,坐标格式: [经度, 纬度]
        [101, 0],
        [101, 1],
        [100, 1],
        [100, 0] // 最后一个坐标点,要跟第一个坐标点相同,这样多边形才能形成闭合
      ]
    ]
  }
}

POST /example/_doc
{
    "location" : "POLYGON ((100.0 0.0, 101.0 0.0, 101.0 1.0, 100.0 1.0, 100.0 0.0))"
}

Elasticsearch地理空间之geo_shape

三、geo_shape地理形状搜索

当索引的字段类型定义为geo_shape之后,我们就可以通过geo_shape实现图形搜索。

1. 图形搜索类型

下面是geo_shape支持的图形搜索类型:

intersects - 查询的形状与索引的形状有重叠(默认), 即图形有交集则匹配。
disjoint - 查询的形状与索引的形状完全不重叠。
within - 查询的形状包含索引的形状。

2.图形搜索例子

GET /example/_search
{
    "query":{
        "bool": { // 布尔组合查询语句
            "must": {
                "match_all": {} // 这里设置其他查询条件,直接匹配全部文档
            },
            "filter": { // 地理信息搜索,通常不参与相关性计算,所以使用filter包裹起来
                "geo_shape": { // geo_shape搜索语句
                    "location": { // 图形数据存储在location字段
                    "relation": "within" // 设置图形搜索类型,这里设置为包含关系
                    "shape": {   //这个可以理解为其实就是geojson的geometry的值
                    	"type": "polygon",  // 设置图形类型,各种图形格式参考geo_shape的数据格式支持的图形类型
                    	"coordinates": [
		                        [
		                            [
		                                104.0396387972344,
		                                30.59613123035072
		                            ],
		                            [
		                                104.0393476378968,
		                                30.59549712177650
		                            ],
		                            [
		                                104.0396387858758,
		                                30.59638313574942
		                            ],
		                            [
		                                104.0396387972344,
		                                30.59613123035072
		                            ]
		                        ]
		                    ]
		                }
                    }
                }
            }
        }
    }
}

四、Java查询代码示例

GeoShape Polygon 查询

  1. 依赖jar包
<dependency>
    <groupId>org.locationtech.jts</groupId>
    <artifactId>jts-core</artifactId>
    <version>1.18.1</version>
</dependency>
<dependency>
    <groupId>org.locationtech.spatial4j</groupId>
    <artifactId>spatial4j</artifactId>
    <version>0.8</version>
</dependency>
  1. 核心代码示例
MultiPolygonBuilder multiPolygonBuilder = new MultiPolygonBuilder();
String shapeField = "";
for (MultiCondition.GeoPolygon geoPolygon : geoPolygons){
    List<Coordinate> coordinateList = geoPolygon.geoPoints.stream().map(point -> new Coordinate(point.getLon(),point.getLat())).collect(Collectors.toList());
    CoordinatesBuilder coordinates = new CoordinatesBuilder().coordinates(coordinateList);
    PolygonBuilder polygonBuilder = new PolygonBuilder(coordinates);
    multiPolygonBuilder.polygon(polygonBuilder);
    shapeField = geoPolygon.getShapeField();
}
try {
    GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery(shapeField, multiPolygonBuilder.buildGeometry());
    queryBuilder.filter(geoShapeQueryBuilder);
} catch (IOException e) {
    e.printStackTrace();
}
  1. 代码示例
package cn.com.example.cdgisdatahandle.config;

import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.geo.ShapeRelation;
import org.elasticsearch.common.geo.builders.CoordinatesBuilder;
import org.elasticsearch.common.geo.builders.MultiPolygonBuilder;
import org.elasticsearch.common.geo.builders.PolygonBuilder;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.GeoShapeQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.MultiPolygon;
import org.locationtech.jts.geom.Polygon;
import org.locationtech.jts.io.WKTReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class ElasticsearchDaoImpl {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Autowired
    private DefConfig defConfig;

    public SearchResponse geoShapeQuery(String wkt) {

        String indexName = defConfig.getEs_realtimepeople_index_name();
        String geoShapeField = defConfig.getEs_realtimepeople_geoshape_field();
        String peopleNumField = defConfig.getEs_realtimepeople_peoplenum_field();

        SearchResponse response = null;
        SearchRequest request = new SearchRequest();
        request.indices(indexName);

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.trackTotalHits(true);
        //查询条件
        BoolQueryBuilder boolQueryBuilder = buildWktBoolQueryBuilder(geoShapeField, wkt);
        boolQueryBuilder.must(QueryBuilders.matchAllQuery());
        boolQueryBuilder.must(QueryBuilders.matchQuery("name", "小明"));
        //聚合求和
        AggregationBuilder agg = AggregationBuilders.sum("aggSum").field(peopleNumField);
        try {
            searchSourceBuilder.query(boolQueryBuilder).aggregation(agg);
            request.source(searchSourceBuilder);
            response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return response;
    }

    /**
     * 构建Wkt条件
     * 参考文章:https://blog.csdn.net/z69183787/article/details/105563778
     *
     * @date 2019/9/26
     */
    private BoolQueryBuilder buildWktBoolQueryBuilder(String queryField, String wkt) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        WKTReader wktReader = new WKTReader();
        try {
            Geometry geom = wktReader.read(wkt);
            GeoShapeQueryBuilder geoShapeQueryBuilder = null;
            if (wkt.startsWith("POLYGON")) {
                Polygon polygon = (Polygon) geom;
                List<Coordinate> coordinateList = Arrays.stream(polygon.getCoordinates()).collect(Collectors.toList());
                CoordinatesBuilder coordinates = new CoordinatesBuilder().coordinates(coordinateList);
                PolygonBuilder polygonBuilder = new PolygonBuilder(coordinates);
                geoShapeQueryBuilder = QueryBuilders.geoShapeQuery(queryField, polygonBuilder.buildGeometry())
                        .relation(ShapeRelation.WITHIN);
                boolQueryBuilder.filter(geoShapeQueryBuilder);
            } else if (wkt.startsWith("MULTIPOLYGON")) {
                MultiPolygon multiPolygon = (MultiPolygon) geom;
                int num = multiPolygon.getNumGeometries();
                MultiPolygonBuilder multiPolygonBuilder = new MultiPolygonBuilder();
                for (int i = 0; i < num; i++) {
                    Polygon polygon = (Polygon) multiPolygon.getGeometryN(i);
                    List<Coordinate> coordinateList = Arrays.stream(polygon.getCoordinates()).collect(Collectors.toList());
                    CoordinatesBuilder coordinates = new CoordinatesBuilder().coordinates(coordinateList);
                    PolygonBuilder polygonBuilder = new PolygonBuilder(coordinates);
                    multiPolygonBuilder.polygon(polygonBuilder);
                }
                geoShapeQueryBuilder = QueryBuilders.geoShapeQuery(queryField, multiPolygonBuilder.buildGeometry())
                        .relation(ShapeRelation.WITHIN);
                boolQueryBuilder.filter(geoShapeQueryBuilder);
            }
        } catch (Exception e) {
            System.out.println("构建Wkt条件错误" + e.getMessage());
        }
        return boolQueryBuilder;
    }

    public static void main(String[] args) {
        ElasticsearchDaoImpl elasticsearchDao = new ElasticsearchDaoImpl();
        String wkt = "POLYGON((110.20111083984375 25.431803168948832,110.05897521972658 25.32075284544021,110.07476806640624 25.187233664941914,110.643310546875 25.1070518051296,110.62477111816405 25.230721136478365,110.55198669433594 25.446064798199416,110.35491943359375 25.353644304321108,110.21072387695312 25.299647958643703,110.17501831054689 25.312683764022793,110.20111083984375 25.431803168948832))";
        string wkt2 = "MULTIPOLYGON (((102.0 2.0, 103.0 2.0, 103.0 3.0, 102.0 3.0, 102.0 2.0)), ((100.0 0.0, 101.0 0.0, 101.0 1.0, 100.0 1.0, 100.0 0.0), (100.2 0.2, 100.8 0.2, 100.8 0.8, 100.2 0.8, 100.2 0.2)))";
        long startCurrentTimeMillis = System.currentTimeMillis();
        elasticsearchDao.geoShapeQuery(wkt);
		elasticsearchDao.geoShapeQuery(wkt2);
        long endCurrentTimeMillis = System.currentTimeMillis();
        System.out.println((endCurrentTimeMillis - startCurrentTimeMillis)/1000 + " s");
    }
}

MultiPolygonBuilder 构建两个多边形,外多边形,内多边形,求环形部分相交数据文章来源地址https://www.toymoban.com/news/detail-405441.html

Coordinate 结构
用一个数组表示 经纬度 坐标点:
[lon,lat]
一组坐标点放到一个数组来表示一个多边形:
[[lon,lat],[lon,lat], ... ]
一个多边形( polygon )形状可以包含多个多边形;第一个表示多边形的外轮廓,后续的多边形表示第一个多边形内部的空洞:
[
  [[lon,lat],[lon,lat], ... ],  # main polygon
  [[lon,lat],[lon,lat], ... ],  # hole in main polygon
  ...
]

到了这里,关于Elasticsearch地理空间之geo_shape的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Elasticsearch 地理空间搜索 - 远超 OpenSearch

    作者:来自 Elastic Nathan_Reese 2021 年,OpenSearch 和 OpenSearch Dashboards 开始作为 Elasticsearch 和 Kibana 的分支。 尽管 OpenSearch 和 OpenSearch Dashboards 具有相似的血统,但它们不提供相同的功能。 在分叉时,只能克隆开源许可的功能。 这给 OpenSearch 留下了一部分功能。 自分叉以来,这种

    2024年02月01日
    浏览(35)
  • Redis GEO地理位置信息的应用

    Redis的GEO操作是一种基于地理位置信息进行操作的功能。它使用经度和纬度坐标来表示地理位置,支持存储地理位置信息用来实现诸如附近位置、摇一摇这类依赖于地理位置信息的功能。 1.GEOADD添加位置信息 将一个或多个指定的地理位置(经度、纬度、名称)添加到指定的键

    2024年02月08日
    浏览(48)
  • 【Redis】特殊数据类型 Geo (地理位置)

    除了五中基本的数据类型外,Redis还支持两种特殊的数据类型,第一种 Geo (地理位置):用于存储地理位置相关的数据,例如经纬度、距离等。第二种 Stream (流):是一个高级的列表类型,支持对列表的批量操作,如添加多个元素、获取多个元素等。 Redis GEO(Geo Redis)是一个用

    2024年02月15日
    浏览(37)
  • Redis GEO 类型与 API 结合,地理位置优化的绝佳实践

    🔭 嗨,您好 👋 我是 vnjohn,在互联网企业担任 Java 开发,CSDN 优质创作者 📖 推荐专栏:Spring、MySQL、Nacos、Java,后续其他专栏会持续优化更新迭代 🌲文章所在专栏:MySQL、Redis、业务设计 🤔 我当前正在学习微服务领域、云原生领域、消息中间件等架构、原理知识 💬 向我

    2024年02月08日
    浏览(33)
  • R语言【paleobioDB】——pbdb_collections_geo():从PBDB获取根据地理位置信息筛选的采集号的基本信息

    Package  paleobioDB  version 0.7.0 paleobioDB 包在2020年已经停止更新,该包依赖PBDB v1 API。 可以选择在Index of /src/contrib/Archive/paleobioDB (r-project.org)下载安装包后,执行本地安装。 参数【...】 :可通过 API 调用的参数。所有可用参数详见 PBDB Data Service: Single fossil collection。 根据参数发

    2024年01月22日
    浏览(35)
  • 285个地级市空间权重矩阵(空间邻接、地理距离、经济距离、经济地理嵌套矩阵)

    285个地级市空间权重矩阵(空间邻接、地理距离、经济距离、经济地理嵌套矩阵) 1、范围:285个地级市 2、数据包括:包括空间邻接矩阵、空间地理距离矩阵、空间经济距离矩阵、空间经济地理嵌套矩阵 其中空间经济距离矩阵根据2003-2019年人均GDP得到 3、指标说明: 空间权

    2024年02月16日
    浏览(57)
  • 地理空间分析12——地理位置数据隐私与安全

    在数字化时代,地理位置数据成为了众多应用程序和服务不可或缺的一部分。从导航应用到社交媒体,从广告定位到城市规划,地理位置数据的应用范围广泛。然而,这些数据的收集和使用也引发了广泛的隐私和安全担忧。本文将探讨地理位置数据隐私的挑战和重要性,并介

    2024年03月19日
    浏览(54)
  • matlab做经济地理、地理距离、经济距离空间权重矩阵

    首先讲下地理加权空间权重矩阵: 该矩阵的经济含义是通过不同点的坐标系之间的距离远近来衡量两地之间的关系重要程度,当两点之间距离较远,所占的权重越低,而距离越近,权重越高。故操作如下: 首先需要导入坐标数据: A=csvread(\\\'JWD.csv\\\',1,0); % JWD.csv是文件名,csvrea

    2023年04月12日
    浏览(37)
  • Elasticsearch ES实现GEO位置搜索

    ES实现GEO位置搜索 Elasticsearch-7.15.2 附近查询,也叫做距离查询(geo_distance):查询到指定中心点小于某个距离值的所有文档。 创建索引 (my_geo),直接设置mapping GEO字段的创建:添加一个字段location,类型为 geo_point。 GEO类型的字段是不能使用动态映射自动生成的,我们需要在创

    2024年01月16日
    浏览(41)
  • kaggle学习笔记-情感和地理空间分析

    秘鲁食品评论中的情绪和地理空间分析 自然语言处理 (NLP) 是人工智能的一个分支,致力于让计算机能够像人类一样理解文本和口语单词。 另一方面,地理空间分析是对图像、GPS、卫星摄影和历史数据的收集、显示和操作,这些数据以地理坐标明确描述,或以街道地址、邮政

    2024年02月16日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包