飞道的博客

Elasticsearch:使用 Elasticsearch 进行地理位置搜索

422人阅读  评论(0)

Elasticsearch 是一个功能强大的搜索引擎,支持地理查询,但并不是每个人都习惯于处理空间数据。 如果你对地理处理了解不多,或者想通过Elasticsearch了解地理处理,那么本文适合你。在我们的现实生活中,我们经常使用的滴滴打车,美团送餐,美国的 Uber, Lyft 打车,还有一些交友 apps 等等,它们都是使用 Elasticsearch 进行位置搜索的例子。

 

Geo distance query

地理距离查询返回距离点最大距离的所有文档,例如:Dolores 想认识距离她约300米的所有人:

红色圆圈的半径为 300 米,我们可以看到只有 William 在圆圈内。

让我们来做一下 Elasticsearch 的实现。 首先,使用属性 name 和 location 创建一个 user_location 索引。


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

location 的数据类型为 geo_point, 表示地球上的位置。 点具有经度和纬度(坐标)。 你可以在官方文档中检查所有可接受的 geo_point 格式。

现在,让我们为 William,Robert 和 Bernard 的位置创建文档。我们使用 _bulk API 来导入数据:


  
  1. POST user_location/_ bulk
  2. { "index" : { "_id" : "1" } }
  3. { "name" : "William", "location": "-25.443053, -49.238396" }
  4. { "index" : { "_id" : "2" } }
  5. { "name" : "Robert", "location": "-25.440173, -49.243169" }
  6. { "index" : { "_id" : "3" } }
  7. { "name" : "Bernard", "location": "-25.440262, -49.247720" }

为了说明问题的方便,我特地创建一个新的索引叫做 locations,它包含了 Dolores 的位置信息:


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

  
  1. POST locations/_ bulk
  2. { "index" : { "_id" : "1" } }
  3. { "name" : "William", "location": "-25.443053, -49.238396" }
  4. { "index" : { "_id" : "2" } }
  5. { "name" : "Robert", "location": "-25.440173, -49.243169" }
  6. { "index" : { "_id" : "3" } }
  7. { "name" : "Bernard", "location": "-25.440262, -49.247720" }
  8. { "index" : { "_id" : "4" } }
  9. { "name" : "Dolores", "location": "-25.442987, -49.239504" }

在上面的 _id 为 4 的文档就是 Doloes 的位置信息。我们来创建一个叫做 locations 的索引模式:

我们打开 Maps 应用:

 

我们发现这四个位置位于南美的某个地方。我们编辑  location 层的设置,当我们点击该位置的时候,显示名字及 id。我们调整合适的 zoom 大小:

从上面的图中,我们很清楚地看到每个人的相对的位置。离 Dolores 最近的就是 Willam,也就是那个被盖着的那个,接着就是 Robert。最远的就是 Bernard。请注意,我们上面的展示都是以 locations 这个索引来进行展示的。它里面含有 Dolores。我们现在使用 user_location 索引来进行搜索:


  
  1. GET user_location/_search
  2. {
  3. "query": {
  4. "bool": {
  5. "filter": {
  6. "geo_distance": {
  7. "distance": "300m",
  8. "location": "-25.442987, -49.239504"
  9. }
  10. }
  11. }
  12. }
  13. }

在上面,我们针对 Dolores 来进行搜索。显示的结果是:


  
  1. {
  2. "took" : 55,
  3. "timed_out" : false,
  4. "_shards" : {
  5. "total" : 1,
  6. "successful" : 1,
  7. "skipped" : 0,
  8. "failed" : 0
  9. },
  10. "hits" : {
  11. "total" : {
  12. "value" : 1,
  13. "relation" : "eq"
  14. },
  15. "max_score" : 0.0,
  16. "hits" : [
  17. {
  18. "_index" : "user_location",
  19. "_type" : "_doc",
  20. "_id" : "1",
  21. "_score" : 0.0,
  22. "_source" : {
  23. "name" : "William",
  24. "location" : "-25.443053, -49.238396"
  25. }
  26. }
  27. ]
  28. }
  29. }

也就是说在 Dolores 方圆 300m 之内,只有 William。如果我们把半径增加到 600 m,那么我可以看到 Robert:


  
  1. GET user_location/_search
  2. {
  3. "query": {
  4. "bool": {
  5. "filter": {
  6. "geo_distance": {
  7. "distance": "600m",
  8. "location": "-25.442987, -49.239504"
  9. }
  10. }
  11. }
  12. }
  13. }

  
  1. {
  2. "took" : 2,
  3. "timed_out" : false,
  4. "_shards" : {
  5. "total" : 1,
  6. "successful" : 1,
  7. "skipped" : 0,
  8. "failed" : 0
  9. },
  10. "hits" : {
  11. "total" : {
  12. "value" : 2,
  13. "relation" : "eq"
  14. },
  15. "max_score" : 0.0,
  16. "hits" : [
  17. {
  18. "_index" : "user_location",
  19. "_type" : "_doc",
  20. "_id" : "1",
  21. "_score" : 0.0,
  22. "_source" : {
  23. "name" : "William",
  24. "location" : "-25.443053, -49.238396"
  25. }
  26. },
  27. {
  28. "_index" : "user_location",
  29. "_type" : "_doc",
  30. "_id" : "2",
  31. "_score" : 0.0,
  32. "_source" : {
  33. "name" : "Robert",
  34. "location" : "-25.440173, -49.243169"
  35. }
  36. }
  37. ]
  38. }
  39. }

Geo polygon query

地理多边形查询可获取多边形内的文档。

“多边形是具有直边的封闭形状。 矩形,三角形,六边形和八边形都是多边形的例子。”

它由点列表表示。 两点之间最接近的路径是一条直线。 多边形的起点和终点均相同。 在下面的图上检查下面的植物园多边形。

请注意,Elasticsearch 上的地理查询会检查文档的 geo_point 属性是否在多边形内。 例:Dolores 想知道植物园内的每个人。


  
  1. GET user_location/_search
  2. {
  3. "query": {
  4. "bool": {
  5. "filter": {
  6. "geo_polygon": {
  7. "location": {
  8. "points": [
  9. "-25.44373,-49.24248",
  10. "-25.44297,-49.24230",
  11. "-25.44177,-49.23642",
  12. "-25.43961,-49.23822",
  13. "-25.43991,-49.23781",
  14. "-25.44170,-49.23647",
  15. "-25.44210,-49.23586",
  16. "-25.44218,-49.23506",
  17. "-25.44358,-49.23491",
  18. "-25.44406,-49.24139",
  19. "-25.44373,-49.24248"
  20. ]
  21. }
  22. }
  23. }
  24. }
  25. }
  26. }

上面的搜索返回的结果:


  
  1. {
  2. "took" : 15,
  3. "timed_out" : false,
  4. "_shards" : {
  5. "total" : 1,
  6. "successful" : 1,
  7. "skipped" : 0,
  8. "failed" : 0
  9. },
  10. "hits" : {
  11. "total" : {
  12. "value" : 1,
  13. "relation" : "eq"
  14. },
  15. "max_score" : 0.0,
  16. "hits" : [
  17. {
  18. "_index" : "user_location",
  19. "_type" : "_doc",
  20. "_id" : "1",
  21. "_score" : 0.0,
  22. "_source" : {
  23. "name" : "William",
  24. "location" : "-25.443053, -49.238396"
  25. }
  26. }
  27. ]
  28. }
  29. }

在本文中,你学习了什么是地理点和地理多边形,以及如何通过 Elasticsearch 实现 geo_distance 和 geo_polygon 查询。 希望本文能对你的知识之旅有所帮助。


转载:https://blog.csdn.net/UbuntuTouch/article/details/109359264
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场