前言
前面我们介绍了在 SpringBoot 中操作 ElasticSearch,进行单条和批量数据的增删改查,ElasticSearch 还支持对地理图形的操作。
这里我们将介绍使用 SpringBoot 在 ElasticSearch 中对地理图形进行操作。
实现
准备工作
前面我们完成了 ELK 环境的搭建,这里我们会使用 Kibana 来观察我们创建出来的图形,以及对索引数据操作均在 Kibana 的可视化界面中进行
创建索引
命令行创建
在 ElasticSearch 的数据类型中,有两种与地理图形相关:
geo_point
:地理坐标点;geo_shape
:地理图形。
使用如下语句创建索引:
- PUT langjialing_index
- {
- "mappings": {
- "properties": {
- "geo_point": {
- "type": "geo_point"
- },
- "geo_shape":{
- "type": "geo_shape"
- }
- }
- }
- }
代码创建
- package com.langjialing.helloworld.controlle1;
- import lombok.extern.slf4j.Slf4j;
- import org.elasticsearch.client.RequestOptions;
- import org.elasticsearch.client.RestHighLevelClient;
- import org.elasticsearch.client.indices.CreateIndexRequest;
- import org.elasticsearch.client.indices.CreateIndexResponse;
- import org.elasticsearch.client.indices.GetIndexRequest;
- import org.elasticsearch.common.settings.Settings;
- import org.elasticsearch.common.xcontent.XContentType;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.GetMapping;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestParam;
- import org.springframework.web.bind.annotation.RestController;
- import java.io.IOException;
- /**
- * @author 郎家岭伯爵
- * @time 2024年6月21日16:47:48
- */
- @RestController
- @RequestMapping("/es4")
- @Slf4j
- public class EsController4 {
- /**
- * Elasticsearch客户端
- */
- @Autowired
- private RestHighLevelClient client;
- /**
- * 创建复杂结构的索引。
- * @param indexName indexName
- * @throws IOException IOException
- */
- @GetMapping("/createIndex")
- public void createIndex(@RequestParam String indexName) throws IOException {
- // 创建索引和映射
- // 判断索引是否存在
- GetIndexRequest getRequest = new GetIndexRequest(indexName);
- boolean exists = client.indices().exists(getRequest, RequestOptions.DEFAULT);
- if (!exists) {
- /**
- * -- 创建索引并指定字段映射
- * PUT langjialing_index
- * {
- * "settings": {
- * "number_of_replicas": 1, // 将副本数设置为1,一般为 节点数 × 1
- * "number_of_shards": 2 // 将分片数设置为2,一般为 节点数 × 2
- * },
- * "mappings": {
- * "properties": {
- * "geo_point": {
- * "type": "geo_point"
- * },
- * "geo_json":{
- * "type": "geo_shape"
- * }
- * }
- * }
- * }
- */
- CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName);
- createIndexRequest.settings(Settings
- .builder()
- .put("index.number_of_shards", 2)
- .put("index.number_of_replicas", 1));
- String mapping = "{\n" +
- " \"properties\": {\n" +
- " \"geo_shape\": {\n" +
- " \"type\": \"geo_shape\"\n" +
- " },\n" +
- " \"geo_point\": {\n" +
- " \"type\": \"geo_point\"\n" +
- " }\n" +
- " }\n" +
- "}";
- createIndexRequest.mapping(mapping, XContentType.JSON);
- CreateIndexResponse createIndexResponse = client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
- }
- }
- }
查看创建出的索引的字段映射:
- GET langjialing_index/_mapping
查看创建出的索引的设置:
- GET langjialing_index/_settings
Kibana配置图形可视化
地理图形操作
Point
geo_shape
也可以存储坐标点数据,它的坐标信息由一个一维数组组成。
命令行创建
- POST langjialing_index/_doc/10
- {
- "geo_shape": {
- "type": "point",
- "coordinates": [ 100, 40 ]
- }
- }
代码创建
- package com.langjialing.helloworld.controlle1;
- import lombok.extern.slf4j.Slf4j;
- import org.elasticsearch.action.index.IndexRequest;
- import org.elasticsearch.client.RequestOptions;
- import org.elasticsearch.client.RestHighLevelClient;
- import org.elasticsearch.common.xcontent.XContentType;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.GetMapping;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestParam;
- import org.springframework.web.bind.annotation.RestController;
- import java.io.IOException;
- /**
- * @author 郎家岭伯爵
- * @time 2024年6月21日16:47:48
- */
- @RestController
- @RequestMapping("/es4")
- @Slf4j
- public class EsController4 {
- /**
- * Elasticsearch客户端
- */
- @Autowired
- private RestHighLevelClient client;
- /**
- * 创建Point点
- * @param indexName 索引名称
- * @param docId 文档ID
- * @throws IOException IOException
- */
- @GetMapping("/createPoint")
- public void createPoint(@RequestParam String indexName, @RequestParam String docId) throws IOException {
- String s = "{\n" +
- " \"geo_shape\": {\n" +
- " \"type\": \"point\",\n" +
- " \"coordinates\": [ 100, 40 ]\n" +
- " }\n" +
- "}";
- // 索引文档
- IndexRequest indexRequest = new IndexRequest(indexName);
- indexRequest.id(docId);
- indexRequest.source(s, XContentType.JSON);
- client.index(indexRequest, RequestOptions.DEFAULT);
- System.out.println("Document indexed successfully.");
- }
- }
Linestring
Linestring
由一个二维数组组成。
我们将创建如下线段:
命令行创建
- POST langjialing_index/_doc/10
- {
- "geo_shape": {
- "type": "LineString",
- "coordinates": [[ 100, 40 ], [100, 45]]
- }
- }
代码创建
- package com.langjialing.helloworld.controlle1;
- import lombok.extern.slf4j.Slf4j;
- import org.elasticsearch.action.index.IndexRequest;
- import org.elasticsearch.client.RequestOptions;
- import org.elasticsearch.client.RestHighLevelClient;
- import org.elasticsearch.common.xcontent.XContentType;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.GetMapping;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestParam;
- import org.springframework.web.bind.annotation.RestController;
- import java.io.IOException;
- /**
- * @author 郎家岭伯爵
- * @time 2024年6月21日16:47:48
- */
- @RestController
- @RequestMapping("/es4")
- @Slf4j
- public class EsController4 {
- /**
- * Elasticsearch客户端
- */
- @Autowired
- private RestHighLevelClient client;
- /**
- * 创建Point点
- * @param indexName 索引名称
- * @param docId 文档ID
- * @throws IOException IOException
- */
- @GetMapping("/createLine")
- public void createLine(@RequestParam String indexName, @RequestParam String docId) throws IOException {
- String s = "{\n" +
- " \"geo_shape\": {\n" +
- " \"type\": \"LineString\",\n" +
- " \"coordinates\": [[ 100, 40 ], [100, 45]]\n" +
- " }\n" +
- "}";
- // 索引文档
- IndexRequest indexRequest = new IndexRequest(indexName);
- indexRequest.id(docId);
- indexRequest.source(s, XContentType.JSON);
- client.index(indexRequest, RequestOptions.DEFAULT);
- System.out.println("Document indexed successfully.");
- }
- }
Polygon
Polygon
的边界信息由一个三维数组组成,可以在多边形中进行挖洞。
接下来我们将在 ElasticSearch 中创建如下 Polygon
图形:
命令行创建
- POST langjialing_index/_doc/10
- {
- "geo_shape": {
- "type": "Polygon",
- "coordinates":
- [
- [
- [ 100, 40 ],
- [ 105, 40 ],
- [ 105, 35 ],
- [ 100, 35 ],
- [ 100, 40 ]
- ],
- [
- [ 102, 38 ],
- [ 104, 38 ],
- [ 104, 36 ],
- [ 102, 36 ],
- [ 102, 38 ]
- ]
- ]
- }
- }
代码创建
- package com.langjialing.helloworld.controlle1;
- import lombok.extern.slf4j.Slf4j;
- import org.elasticsearch.action.index.IndexRequest;
- import org.elasticsearch.client.RequestOptions;
- import org.elasticsearch.client.RestHighLevelClient;
- import org.elasticsearch.common.xcontent.XContentType;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.GetMapping;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestParam;
- import org.springframework.web.bind.annotation.RestController;
- import java.io.IOException;
- /**
- * @author 郎家岭伯爵
- * @time 2024年6月21日16:47:48
- */
- @RestController
- @RequestMapping("/es4")
- @Slf4j
- public class EsController4 {
- /**
- * Elasticsearch客户端
- */
- @Autowired
- private RestHighLevelClient client;
- /**
- * 创建Polygon图形
- * @param indexName 索引名称
- * @param docId 文档ID
- * @throws IOException IOException
- */
- @GetMapping("/createPolygon")
- public void createPolygon(@RequestParam String indexName, @RequestParam String docId) throws IOException {
- String s = "{\n" +
- " \"geo_shape\": {\n" +
- " \"type\": \"Polygon\",\n" +
- " \"coordinates\": \n" +
- " [\n" +
- " [\n" +
- " [ 100, 40 ],\n" +
- " [ 105, 40 ],\n" +
- " [ 105, 35 ],\n" +
- " [ 100, 35 ],\n" +
- " [ 100, 40 ]\n" +
- " ],\n" +
- " [\n" +
- " [ 102, 38 ],\n" +
- " [ 104, 38 ],\n" +
- " [ 104, 36 ],\n" +
- " [ 102, 36 ],\n" +
- " [ 102, 38 ]\n" +
- " ]\n" +
- " ]\n" +
- " }\n" +
- "}";
- // 索引文档
- IndexRequest indexRequest = new IndexRequest(indexName);
- indexRequest.id(docId);
- indexRequest.source(s, XContentType.JSON);
- client.index(indexRequest, RequestOptions.DEFAULT);
- System.out.println("Document indexed successfully.");
- }
- }
MultiPolygon
MutiPolygon
是 ElasticSearch 中最为复杂的图形,它的边界信息由一个四维数组组成,其中有多个挖洞、飞地等部分。
接下来我们将在 ElasticSearch 中创建如下 MultiPolygon
图形:
命令行创建
- POST langjialing_index/_doc/10
- {
- "geo_shape": {
- "type": "MultiPolygon",
- "coordinates": [
- [
- [
- [ 100, 40 ],
- [ 105, 40 ],
- [ 105, 35 ],
- [ 100, 35 ],
- [ 100, 40 ]
- ],
- [
- [ 102, 38 ],
- [ 104, 38 ],
- [ 104, 36 ],
- [ 102, 36 ],
- [ 102, 38 ]
- ]
- ],
- [
- [
- [ 120, 40 ],
- [ 123, 40 ],
- [ 123, 37 ],
- [ 120, 37 ],
- [ 120, 40 ]
- ]
- ]
- ]
- }
- }
代码创建
- package com.langjialing.helloworld.controlle1;
- import lombok.extern.slf4j.Slf4j;
- import org.elasticsearch.action.index.IndexRequest;
- import org.elasticsearch.client.RequestOptions;
- import org.elasticsearch.client.RestHighLevelClient;
- import org.elasticsearch.common.xcontent.XContentType;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.GetMapping;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestParam;
- import org.springframework.web.bind.annotation.RestController;
- import java.io.IOException;
- /**
- * @author 郎家岭伯爵
- * @time 2024年6月21日16:47:48
- */
- @RestController
- @RequestMapping("/es4")
- @Slf4j
- public class EsController4 {
- /**
- * Elasticsearch客户端
- */
- @Autowired
- private RestHighLevelClient client;
- /**
- * 创建MultiPolygon图形
- * @param indexName 索引名称
- * @param docId 文档ID
- * @throws IOException IOException
- */
- @GetMapping("/createMultiPolygon")
- public void createMultiPolygon(@RequestParam String indexName, @RequestParam String docId) throws IOException {
- // 这里是一个JSON格式的字符串。
- String s = "{\n" +
- " \"geo_shape\": {\n" +
- " \"coordinates\": [\n" +
- " [\n" +
- " [\n" +
- " [\n" +
- " 100.0,\n" +
- " 40.0\n" +
- " ],\n" +
- " [\n" +
- " 105.0,\n" +
- " 40.0\n" +
- " ],\n" +
- " [\n" +
- " 105.0,\n" +
- " 35.0\n" +
- " ],\n" +
- " [\n" +
- " 100.0,\n" +
- " 35.0\n" +
- " ],\n" +
- " [\n" +
- " 100.0,\n" +
- " 40.0\n" +
- " ]\n" +
- " ],\n" +
- " [\n" +
- " [\n" +
- " 102.0,\n" +
- " 38.0\n" +
- " ],\n" +
- " [\n" +
- " 104.0,\n" +
- " 38.0\n" +
- " ],\n" +
- " [\n" +
- " 104.0,\n" +
- " 36.0\n" +
- " ],\n" +
- " [\n" +
- " 102.0,\n" +
- " 36.0\n" +
- " ],\n" +
- " [\n" +
- " 102.0,\n" +
- " 38.0\n" +
- " ]\n" +
- " ]\n" +
- " ],\n" +
- " [\n" +
- " [\n" +
- " [\n" +
- " 120.0,\n" +
- " 40.0\n" +
- " ],\n" +
- " [\n" +
- " 123.0,\n" +
- " 40.0\n" +
- " ],\n" +
- " [\n" +
- " 123.0,\n" +
- " 37.0\n" +
- " ],\n" +
- " [\n" +
- " 120.0,\n" +
- " 37.0\n" +
- " ],\n" +
- " [\n" +
- " 120.0,\n" +
- " 40.0\n" +
- " ]\n" +
- " ]\n" +
- " ]\n" +
- " ],\n" +
- " \"type\": \"MultiPolygon\"\n" +
- " }\n" +
- "}";
- // 索引文档
- IndexRequest indexRequest = new IndexRequest(indexName);
- indexRequest.id(docId);
- indexRequest.source(s, XContentType.JSON);
- client.index(indexRequest, RequestOptions.DEFAULT);
- System.out.println("Document indexed successfully.");
- }
- }
总结
SpringBoot 整合 ElasticSearch,操作复杂图形。
以上几种图形的操作,本质是一样的,都是在 ElasticSearch 中对 geo_shape
类型的数据进行的基本操作。