ElasticSearch:SpringBoot整合 - 复杂图形的使用

郎家岭伯爵 2024年06月21日 544次浏览

前言

前面我们介绍了在 SpringBoot 中操作 ElasticSearch,进行单条批量数据的增删改查,ElasticSearch 还支持对地理图形的操作。

这里我们将介绍使用 SpringBoot 在 ElasticSearch 中对地理图形进行操作。

实现

准备工作

前面我们完成了 ELK 环境的搭建,这里我们会使用 Kibana 来观察我们创建出来的图形,以及对索引数据操作均在 Kibana 的可视化界面中进行

创建索引

命令行创建

在 ElasticSearch 的数据类型中,有两种与地理图形相关:

  • geo_point:地理坐标点;
  • geo_shape:地理图形。

使用如下语句创建索引:

  1. PUT langjialing_index
  2. {
  3. "mappings": {
  4. "properties": {
  5. "geo_point": {
  6. "type": "geo_point"
  7. },
  8. "geo_shape":{
  9. "type": "geo_shape"
  10. }
  11. }
  12. }
  13. }

代码创建

  1. package com.langjialing.helloworld.controlle1;

  2. import lombok.extern.slf4j.Slf4j;
  3. import org.elasticsearch.client.RequestOptions;
  4. import org.elasticsearch.client.RestHighLevelClient;
  5. import org.elasticsearch.client.indices.CreateIndexRequest;
  6. import org.elasticsearch.client.indices.CreateIndexResponse;
  7. import org.elasticsearch.client.indices.GetIndexRequest;
  8. import org.elasticsearch.common.settings.Settings;
  9. import org.elasticsearch.common.xcontent.XContentType;
  10. import org.springframework.beans.factory.annotation.Autowired;
  11. import org.springframework.web.bind.annotation.GetMapping;
  12. import org.springframework.web.bind.annotation.RequestMapping;
  13. import org.springframework.web.bind.annotation.RequestParam;
  14. import org.springframework.web.bind.annotation.RestController;

  15. import java.io.IOException;

  16. /**
  17. * @author 郎家岭伯爵
  18. * @time 2024年6月21日16:47:48
  19. */

  20. @RestController
  21. @RequestMapping("/es4")
  22. @Slf4j
  23. public class EsController4 {

  24. /**
  25. * Elasticsearch客户端
  26. */
  27. @Autowired
  28. private RestHighLevelClient client;

  29. /**
  30. * 创建复杂结构的索引。
  31. * @param indexName indexName
  32. * @throws IOException IOException
  33. */
  34. @GetMapping("/createIndex")
  35. public void createIndex(@RequestParam String indexName) throws IOException {

  36. // 创建索引和映射
  37. // 判断索引是否存在
  38. GetIndexRequest getRequest = new GetIndexRequest(indexName);
  39. boolean exists = client.indices().exists(getRequest, RequestOptions.DEFAULT);
  40. if (!exists) {
  41. /**
  42. * -- 创建索引并指定字段映射
  43. * PUT langjialing_index
  44. * {
  45. * "settings": {
  46. * "number_of_replicas": 1, // 将副本数设置为1,一般为 节点数 × 1
  47. * "number_of_shards": 2 // 将分片数设置为2,一般为 节点数 × 2
  48. * },
  49. * "mappings": {
  50. * "properties": {
  51. * "geo_point": {
  52. * "type": "geo_point"
  53. * },
  54. * "geo_json":{
  55. * "type": "geo_shape"
  56. * }
  57. * }
  58. * }
  59. * }
  60. */
  61. CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName);
  62. createIndexRequest.settings(Settings
  63. .builder()
  64. .put("index.number_of_shards", 2)
  65. .put("index.number_of_replicas", 1));
  66. String mapping = "{\n" +
  67. " \"properties\": {\n" +
  68. " \"geo_shape\": {\n" +
  69. " \"type\": \"geo_shape\"\n" +
  70. " },\n" +
  71. " \"geo_point\": {\n" +
  72. " \"type\": \"geo_point\"\n" +
  73. " }\n" +
  74. " }\n" +
  75. "}";
  76. createIndexRequest.mapping(mapping, XContentType.JSON);
  77. CreateIndexResponse createIndexResponse = client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
  78. }
  79. }
  80. }

查看创建出的索引的字段映射

  1. GET langjialing_index/_mapping

查看创建出的索引的设置

  1. GET langjialing_index/_settings

Kibana配置图形可视化

  1. 配置索引:

  2. 选择索引:

  3. 选择要展示的索引:

  4. 选择数据类型:

  5. 设置图形颜色并保存:

  6. 刷新展示的数据:

地理图形操作

Point

geo_shape 也可以存储坐标点数据,它的坐标信息由一个一维数组组成。

命令行创建

  1. POST langjialing_index/_doc/10
  2. {
  3. "geo_shape": {
  4. "type": "point",
  5. "coordinates": [ 100, 40 ]
  6. }
  7. }

代码创建

  1. package com.langjialing.helloworld.controlle1;

  2. import lombok.extern.slf4j.Slf4j;
  3. import org.elasticsearch.action.index.IndexRequest;
  4. import org.elasticsearch.client.RequestOptions;
  5. import org.elasticsearch.client.RestHighLevelClient;
  6. import org.elasticsearch.common.xcontent.XContentType;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.web.bind.annotation.GetMapping;
  9. import org.springframework.web.bind.annotation.RequestMapping;
  10. import org.springframework.web.bind.annotation.RequestParam;
  11. import org.springframework.web.bind.annotation.RestController;

  12. import java.io.IOException;

  13. /**
  14. * @author 郎家岭伯爵
  15. * @time 2024年6月21日16:47:48
  16. */

  17. @RestController
  18. @RequestMapping("/es4")
  19. @Slf4j
  20. public class EsController4 {

  21. /**
  22. * Elasticsearch客户端
  23. */
  24. @Autowired
  25. private RestHighLevelClient client;

  26. /**
  27. * 创建Point点
  28. * @param indexName 索引名称
  29. * @param docId 文档ID
  30. * @throws IOException IOException
  31. */
  32. @GetMapping("/createPoint")
  33. public void createPoint(@RequestParam String indexName, @RequestParam String docId) throws IOException {

  34. String s = "{\n" +
  35. " \"geo_shape\": {\n" +
  36. " \"type\": \"point\",\n" +
  37. " \"coordinates\": [ 100, 40 ]\n" +
  38. " }\n" +
  39. "}";

  40. // 索引文档
  41. IndexRequest indexRequest = new IndexRequest(indexName);
  42. indexRequest.id(docId);
  43. indexRequest.source(s, XContentType.JSON);
  44. client.index(indexRequest, RequestOptions.DEFAULT);

  45. System.out.println("Document indexed successfully.");
  46. }
  47. }

Linestring

Linestring 由一个二维数组组成。

我们将创建如下线段:

image-1718963500182

image-1718963500182

命令行创建

  1. POST langjialing_index/_doc/10
  2. {
  3. "geo_shape": {
  4. "type": "LineString",
  5. "coordinates": [[ 100, 40 ], [100, 45]]
  6. }
  7. }

代码创建

  1. package com.langjialing.helloworld.controlle1;

  2. import lombok.extern.slf4j.Slf4j;
  3. import org.elasticsearch.action.index.IndexRequest;
  4. import org.elasticsearch.client.RequestOptions;
  5. import org.elasticsearch.client.RestHighLevelClient;
  6. import org.elasticsearch.common.xcontent.XContentType;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.web.bind.annotation.GetMapping;
  9. import org.springframework.web.bind.annotation.RequestMapping;
  10. import org.springframework.web.bind.annotation.RequestParam;
  11. import org.springframework.web.bind.annotation.RestController;

  12. import java.io.IOException;

  13. /**
  14. * @author 郎家岭伯爵
  15. * @time 2024年6月21日16:47:48
  16. */

  17. @RestController
  18. @RequestMapping("/es4")
  19. @Slf4j
  20. public class EsController4 {

  21. /**
  22. * Elasticsearch客户端
  23. */
  24. @Autowired
  25. private RestHighLevelClient client;

  26. /**
  27. * 创建Point点
  28. * @param indexName 索引名称
  29. * @param docId 文档ID
  30. * @throws IOException IOException
  31. */
  32. @GetMapping("/createLine")
  33. public void createLine(@RequestParam String indexName, @RequestParam String docId) throws IOException {

  34. String s = "{\n" +
  35. " \"geo_shape\": {\n" +
  36. " \"type\": \"LineString\",\n" +
  37. " \"coordinates\": [[ 100, 40 ], [100, 45]]\n" +
  38. " }\n" +
  39. "}";

  40. // 索引文档
  41. IndexRequest indexRequest = new IndexRequest(indexName);
  42. indexRequest.id(docId);
  43. indexRequest.source(s, XContentType.JSON);
  44. client.index(indexRequest, RequestOptions.DEFAULT);

  45. System.out.println("Document indexed successfully.");
  46. }
  47. }

Polygon

Polygon 的边界信息由一个三维数组组成,可以在多边形中进行挖洞。

接下来我们将在 ElasticSearch 中创建如下 Polygon 图形:

命令行创建

  1. POST langjialing_index/_doc/10
  2. {
  3. "geo_shape": {
  4. "type": "Polygon",
  5. "coordinates":
  6. [
  7. [
  8. [ 100, 40 ],
  9. [ 105, 40 ],
  10. [ 105, 35 ],
  11. [ 100, 35 ],
  12. [ 100, 40 ]
  13. ],
  14. [
  15. [ 102, 38 ],
  16. [ 104, 38 ],
  17. [ 104, 36 ],
  18. [ 102, 36 ],
  19. [ 102, 38 ]
  20. ]
  21. ]
  22. }
  23. }

代码创建

  1. package com.langjialing.helloworld.controlle1;

  2. import lombok.extern.slf4j.Slf4j;
  3. import org.elasticsearch.action.index.IndexRequest;
  4. import org.elasticsearch.client.RequestOptions;
  5. import org.elasticsearch.client.RestHighLevelClient;
  6. import org.elasticsearch.common.xcontent.XContentType;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.web.bind.annotation.GetMapping;
  9. import org.springframework.web.bind.annotation.RequestMapping;
  10. import org.springframework.web.bind.annotation.RequestParam;
  11. import org.springframework.web.bind.annotation.RestController;

  12. import java.io.IOException;

  13. /**
  14. * @author 郎家岭伯爵
  15. * @time 2024年6月21日16:47:48
  16. */

  17. @RestController
  18. @RequestMapping("/es4")
  19. @Slf4j
  20. public class EsController4 {

  21. /**
  22. * Elasticsearch客户端
  23. */
  24. @Autowired
  25. private RestHighLevelClient client;

  26. /**
  27. * 创建Polygon图形
  28. * @param indexName 索引名称
  29. * @param docId 文档ID
  30. * @throws IOException IOException
  31. */
  32. @GetMapping("/createPolygon")
  33. public void createPolygon(@RequestParam String indexName, @RequestParam String docId) throws IOException {

  34. String s = "{\n" +
  35. " \"geo_shape\": {\n" +
  36. " \"type\": \"Polygon\",\n" +
  37. " \"coordinates\": \n" +
  38. " [\n" +
  39. " [\n" +
  40. " [ 100, 40 ],\n" +
  41. " [ 105, 40 ],\n" +
  42. " [ 105, 35 ],\n" +
  43. " [ 100, 35 ],\n" +
  44. " [ 100, 40 ]\n" +
  45. " ],\n" +
  46. " [\n" +
  47. " [ 102, 38 ],\n" +
  48. " [ 104, 38 ],\n" +
  49. " [ 104, 36 ],\n" +
  50. " [ 102, 36 ],\n" +
  51. " [ 102, 38 ]\n" +
  52. " ]\n" +
  53. " ]\n" +
  54. " }\n" +
  55. "}";

  56. // 索引文档
  57. IndexRequest indexRequest = new IndexRequest(indexName);
  58. indexRequest.id(docId);
  59. indexRequest.source(s, XContentType.JSON);
  60. client.index(indexRequest, RequestOptions.DEFAULT);

  61. System.out.println("Document indexed successfully.");
  62. }
  63. }

MultiPolygon

MutiPolygon 是 ElasticSearch 中最为复杂的图形,它的边界信息由一个四维数组组成,其中有多个挖洞、飞地等部分。

接下来我们将在 ElasticSearch 中创建如下 MultiPolygon 图形:

命令行创建

  1. POST langjialing_index/_doc/10
  2. {
  3. "geo_shape": {
  4. "type": "MultiPolygon",
  5. "coordinates": [
  6. [
  7. [
  8. [ 100, 40 ],
  9. [ 105, 40 ],
  10. [ 105, 35 ],
  11. [ 100, 35 ],
  12. [ 100, 40 ]
  13. ],
  14. [
  15. [ 102, 38 ],
  16. [ 104, 38 ],
  17. [ 104, 36 ],
  18. [ 102, 36 ],
  19. [ 102, 38 ]
  20. ]
  21. ],
  22. [
  23. [
  24. [ 120, 40 ],
  25. [ 123, 40 ],
  26. [ 123, 37 ],
  27. [ 120, 37 ],
  28. [ 120, 40 ]
  29. ]
  30. ]
  31. ]
  32. }
  33. }

代码创建

  1. package com.langjialing.helloworld.controlle1;

  2. import lombok.extern.slf4j.Slf4j;
  3. import org.elasticsearch.action.index.IndexRequest;
  4. import org.elasticsearch.client.RequestOptions;
  5. import org.elasticsearch.client.RestHighLevelClient;
  6. import org.elasticsearch.common.xcontent.XContentType;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.web.bind.annotation.GetMapping;
  9. import org.springframework.web.bind.annotation.RequestMapping;
  10. import org.springframework.web.bind.annotation.RequestParam;
  11. import org.springframework.web.bind.annotation.RestController;

  12. import java.io.IOException;

  13. /**
  14. * @author 郎家岭伯爵
  15. * @time 2024年6月21日16:47:48
  16. */

  17. @RestController
  18. @RequestMapping("/es4")
  19. @Slf4j
  20. public class EsController4 {

  21. /**
  22. * Elasticsearch客户端
  23. */
  24. @Autowired
  25. private RestHighLevelClient client;

  26. /**
  27. * 创建MultiPolygon图形
  28. * @param indexName 索引名称
  29. * @param docId 文档ID
  30. * @throws IOException IOException
  31. */
  32. @GetMapping("/createMultiPolygon")
  33. public void createMultiPolygon(@RequestParam String indexName, @RequestParam String docId) throws IOException {

  34. // 这里是一个JSON格式的字符串。
  35. String s = "{\n" +
  36. " \"geo_shape\": {\n" +
  37. " \"coordinates\": [\n" +
  38. " [\n" +
  39. " [\n" +
  40. " [\n" +
  41. " 100.0,\n" +
  42. " 40.0\n" +
  43. " ],\n" +
  44. " [\n" +
  45. " 105.0,\n" +
  46. " 40.0\n" +
  47. " ],\n" +
  48. " [\n" +
  49. " 105.0,\n" +
  50. " 35.0\n" +
  51. " ],\n" +
  52. " [\n" +
  53. " 100.0,\n" +
  54. " 35.0\n" +
  55. " ],\n" +
  56. " [\n" +
  57. " 100.0,\n" +
  58. " 40.0\n" +
  59. " ]\n" +
  60. " ],\n" +
  61. " [\n" +
  62. " [\n" +
  63. " 102.0,\n" +
  64. " 38.0\n" +
  65. " ],\n" +
  66. " [\n" +
  67. " 104.0,\n" +
  68. " 38.0\n" +
  69. " ],\n" +
  70. " [\n" +
  71. " 104.0,\n" +
  72. " 36.0\n" +
  73. " ],\n" +
  74. " [\n" +
  75. " 102.0,\n" +
  76. " 36.0\n" +
  77. " ],\n" +
  78. " [\n" +
  79. " 102.0,\n" +
  80. " 38.0\n" +
  81. " ]\n" +
  82. " ]\n" +
  83. " ],\n" +
  84. " [\n" +
  85. " [\n" +
  86. " [\n" +
  87. " 120.0,\n" +
  88. " 40.0\n" +
  89. " ],\n" +
  90. " [\n" +
  91. " 123.0,\n" +
  92. " 40.0\n" +
  93. " ],\n" +
  94. " [\n" +
  95. " 123.0,\n" +
  96. " 37.0\n" +
  97. " ],\n" +
  98. " [\n" +
  99. " 120.0,\n" +
  100. " 37.0\n" +
  101. " ],\n" +
  102. " [\n" +
  103. " 120.0,\n" +
  104. " 40.0\n" +
  105. " ]\n" +
  106. " ]\n" +
  107. " ]\n" +
  108. " ],\n" +
  109. " \"type\": \"MultiPolygon\"\n" +
  110. " }\n" +
  111. "}";
  112. // 索引文档
  113. IndexRequest indexRequest = new IndexRequest(indexName);
  114. indexRequest.id(docId);
  115. indexRequest.source(s, XContentType.JSON);
  116. client.index(indexRequest, RequestOptions.DEFAULT);

  117. System.out.println("Document indexed successfully.");
  118. }
  119. }

总结

SpringBoot 整合 ElasticSearch,操作复杂图形

以上几种图形的操作,本质是一样的,都是在 ElasticSearch 中对 geo_shape 类型的数据进行的基本操作。