ElasticSearch位置搜索 - Spring , Hadoop, Spark , BI , ML - CSDN博客

标签: | 发表时间:2018-11-09 10:33 | 作者:
出处:https://blog.csdn.net

在ElasticSearch中,地理位置通过 geo_point这个数据类型来支持。地理位置的数据需要提供经纬度信息,当经纬度不合法时,ES会拒绝新增文档。这种类型的数据支持距离计算,范围查询等。在底层,索引使用 Geohash实现。

1、创建索引

PUT创建一个索引 cn_large_cities, mapping为city:

      {
    "mappings":{
        "city":{
            "properties":{
                "city":{"type":"string"},
                "state":{"type":"string"},
                "location":{"type":"geo_point"}}}}}

geo_point类型必须显示指定,ES无法从数据中推断。在ES中,位置数据可以通过对象,字符串,数组三种形式表示,分别如下:

      #"lat,lon""location":"40.715,-74.011""location": {
  "lat":40.715,
  "lon":-74.011}

# [lon ,lat]"location":[-74.011,40.715]

POST下面4条测试数据:

      {"city":"Beijing", "state":"BJ","location":{"lat":"39.91667", "lon":"116.41667"}}

{"city":"Shanghai", "state":"SH","location":{"lat":"34.50000", "lon":"121.43333"}}

{"city":"Xiamen", "state":"FJ","location":{"lat":"24.46667", "lon":"118.10000"}}

{"city":"Fuzhou", "state":"FJ","location":{"lat":"26.08333", "lon":"119.30000"}}

{"city":"Guangzhou", "state":"GD","location":{"lat":"23.16667", "lon":"113.23333"}}

查看全部文档:

      curl -XGET"http://localhost:9200/cn_large_cities/city/_search?pretty=true"

返回全部的5条数据,score均为1:

这里写图片描述

2、位置过滤

ES中有4中位置相关的过滤器,用于过滤位置信息:

  • geo_distance: 查找距离某个中心点距离在一定范围内的位置
  • geo_bounding_box: 查找某个长方形区域内的位置
  • geo_distance_range: 查找距离某个中心的距离在min和max之间的位置
  • geo_polygon: 查找位于多边形内的地点。

geo_distance

该类型过滤器查找的范围如下图:

下面是一个查询例子:

      {
  "query":{
    "filtered":{
      "filter":{
        "geo_distance":"1km",
        "location":{
          "lat":40.715,
          "lon":-73.988}}}}}

以下查询,查找距厦门500公里以内的城市:

      {
    "query":{
        "filtered":{
          "filter":{
            "geo_distance" :{
                "distance" :"500km",
                "location" :{
                    "lat" :24.46667,
                    "lon" :118.10000}}}}}}

geo_distance_range

      {
  "query":{
    "filtered":{
      "filter":{
        "geo_distance_range":{
        "gte":"1km",
        "lt":"2km",
        "location":{
          "lat":40.715,
          "lon":-73.988}}}}}

geo_bounding_box

      {
  "query":{
    "filtered":{
      "filter":{
        "geo_bounding_box":{
        "location":{
          "top_left":{
            "lat":40.8,
            "lon":-74.0},
          "bottom_right":{
            "lat":40.715,
            "lon":-73.0}}}}}}

3、按距离排序

接着我们按照距离厦门远近查找:

      {
  "sort" :[
      {
          "_geo_distance" :{
              "location" :{
                    "lat" :24.46667,
                    "lon" :118.10000}, 
              "order" :"asc",
              "unit" :"km"}}
  ],
  "query":{
    "filtered" :{
        "query" :{
            "match_all" :{}}}}}

结果如下,依次是厦门、福州、广州…。符合我们的常识:

      {
  "took":8,
  "timed_out":false,
  "_shards":{
    "total":5,
    "successful":5,
    "failed":0},
  "hits":{
    "total":5,
    "max_score":null,
    "hits":[
      {
        "_index":"us_large_cities",
        "_type":"city",
        "_id":"AVaiSGXXjL0tfmRppc_p",
        "_score":null,
        "_source":{
          "city":"Xiamen",
          "state":"FJ",
          "location":{
            "lat":"24.46667",
            "lon":"118.10000"}},
        "sort":[0]},
      {
        "_index":"us_large_cities",
        "_type":"city",
        "_id":"AVaiSSuNjL0tfmRppc_r",
        "_score":null,
        "_source":{
          "city":"Fuzhou",
          "state":"FJ",
          "location":{
            "lat":"26.08333",
            "lon":"119.30000"}},
        "sort":[216.61105485607183]},
      {
        "_index":"us_large_cities",
        "_type":"city",
        "_id":"AVaiSd02jL0tfmRppc_s",
        "_score":null,
        "_source":{
          "city":"Guangzhou",
          "state":"GD",
          "location":{
            "lat":"23.16667",
            "lon":"113.23333"}},
        "sort":[515.9964950041397]},
      {
        "_index":"us_large_cities",
        "_type":"city",
        "_id":"AVaiR7_5jL0tfmRppc_o",
        "_score":null,
        "_source":{
          "city":"Shanghai",
          "state":"SH",
          "location":{
            "lat":"34.50000",
            "lon":"121.43333"}},
        "sort":[1161.512141925948]},
      {
        "_index":"us_large_cities",
        "_type":"city",
        "_id":"AVaiRwLUjL0tfmRppc_n",
        "_score":null,
        "_source":{
          "city":"Beijing",
          "state":"BJ",
          "location":{
            "lat":"39.91667",
            "lon":"116.41667"}},
        "sort":[1725.4543712286697]}
    ]}}

结果返回的sort字段是指公里数。加上限制条件,只返回最近的一个城市:

      {

  "from":0,
  "size":1,
  "sort" :[
      {
          "_geo_distance" :{
              "location" :{
                    "lat" :24.46667,
                    "lon" :118.10000}, 
              "order" :"asc",
              "unit" :"km"}}
  ],
  "query":{
    "filtered" :{
        "query" :{
            "match_all" :{}}}}}

4、地理位置聚合

ES提供了3种位置聚合:

  • geo_distance: 根据到特定中心点的距离聚合
  • geohash_grid: 根据Geohash的单元格(cell)聚合
  • geo_bounds: 根据区域聚合

4.1 geo_distance聚合

下面这个查询根据距离厦门的距离来聚合,返回0-500,500-8000km的聚合:

      {
    "query":{
        "filtered":{
            "filter":{
                "geo_distance" :{
                    "distance" :"10000km",
                    "location" :{
                        "lat" :24.46667,
                        "lon" :118.10000}}}}},
    "aggs":{
        "per_ring":{
            "geo_distance":{
                "field":"location",
                "unit":"km",
                "origin":{
                    "lat" :24.46667,
                    "lon" :118.10000},
                "ranges":[
                    {"from":0, "to":500},
                    {"from":500, "to":8000}
                ]}}}}

返回的聚合结果如下;

      "aggregations": {
    "per_ring":{
      "buckets":[
        {
          "key":"*-500.0",
          "from":0,
          "from_as_string":"0.0",
          "to":500,
          "to_as_string":"500.0",
          "doc_count":2},
        {
          "key":"500.0-8000.0",
          "from":500,
          "from_as_string":"500.0",
          "to":8000,
          "to_as_string":"8000.0",
          "doc_count":3}
      ]}}

可以看到,距离厦门0-500km的城市有2个,500-8000km的有3个。

4.2 geohash_grid聚合

该聚合方式根据geo_point数据对应的geohash值所在的cell进行聚合,cell的划分精度通过 precision属性来控制,精度是指cell划分的次数。

      {
    "query":{
        "filtered":{
            "filter":{
                "geo_distance" :{
                    "distance" :"10000km",
                    "location" :{
                        "lat" :24.46667,
                        "lon" :118.10000}}}}},
    "aggs":{
        "grid_agg":{
            "geohash_grid":{
                "field":"location",
                "precision":2}}}}

聚合结果如下:

      "aggregations": {
    "grid_agg":{
      "buckets":[
        {
          "key":"ws",
          "doc_count":3},
        {
          "key":"wx",
          "doc_count":1},
        {
          "key":"ww",
          "doc_count":1}
      ]}}

可以看到,有3个城市的的geohash值为ws。将精度提高到5,聚合结果如下:

      "aggregations": {
    "grid_agg":{
      "buckets":[
        {
          "key":"wx4g1",
          "doc_count":1},
        {
          "key":"wwnk7",
          "doc_count":1},
        {
          "key":"wssu6",
          "doc_count":1},
        {
          "key":"ws7gp",
          "doc_count":1},
        {
          "key":"ws0eb",
          "doc_count":1}
      ]}}

4.3 geo_bounds聚合

这个聚合操作计算能够覆盖所有查询结果中geo_point的最小区域,返回的是覆盖所有位置的最小矩形:

      {
    "query":{
        "filtered":{
            "filter":{
                "geo_distance" :{
                    "distance" :"10000km",
                    "location" :{
                        "lat" :24.46667,
                        "lon" :118.10000}}}}},
    "aggs":{
        "map-zoom":{
            "geo_bounds":{
                "field":"location"}}}}

结果如下:

      "aggregations": {
    "map-zoom":{
      "bounds":{
        "top_left":{
          "lat":39.91666993126273,
          "lon":113.2333298586309},
        "bottom_right":{
          "lat":23.16666992381215,
          "lon":121.43332997336984}}}}

也就是说,这两个点构成的矩形能够包含所有到厦门距离10000km的区域。我们把距离调整为500km,此时覆盖这些城市的矩形如下:

      "aggregations": {
    "map-zoom":{
      "bounds":{
        "top_left":{
          "lat":26.083329990506172,
          "lon":118.0999999679625},
        "bottom_right":{
          "lat":24.46666999720037,
          "lon":119.29999999701977}}}}

5、参考资料

图解 MongoDB 地理位置索引的实现原理: http://blog.nosqlfan.com/html/1811.html
Geopoint数据类型: https://www.elastic.co/guide/en/elasticsearch/reference/current/geo-point.html

相关 [elasticsearch 位置 搜索] 推荐:

ElasticSearch位置搜索 - Spring , Hadoop, Spark , BI , ML - CSDN博客

- -
在ElasticSearch中,地理位置通过. geo_point这个数据类型来支持. 地理位置的数据需要提供经纬度信息,当经纬度不合法时,ES会拒绝新增文档. 这种类型的数据支持距离计算,范围查询等. mapping为city:. geo_point类型必须显示指定,ES无法从数据中推断. 在ES中,位置数据可以通过对象,字符串,数组三种形式表示,分别如下:.

[Elasticsearch] 分布式搜索

- - 编程语言 - ITeye博客
本文翻译自Elasticsearch官方指南的 Distributed Search Execution一章. 在继续之前,我们将绕一段路来谈谈在分布式环境中,搜索是如何执行的. 和在分布式文档存储(Distributed Document Store)中讨论的基本CRUD操作相比,这个过程会更加复杂一些.

ElasticSearch入门-搜索如此简单

- - ITeye博客
搜索引擎我也不是很熟悉,但是数据库还是比较了解. 可以把搜索理解为数据库的like功能的替代品. 第一、like的效率不行,在使用like时,一般都用不到索引,除非使用前缀匹配,才能用得上索引. 第二、like的不能做到完全的模糊匹配. 比如like '%化痰冲剂%'就不能把”化痰止咳冲剂“搜索出来.

Elasticsearch搜索类型(query type)详解

- - ITeye博客
欢迎发送邮件至 donlianli@126.com. 请支持原创 http://donlianli.iteye.com/blog/2094305. es在查询时,可以指定搜索类型为QUERY_THEN_FETCH,QUERY_AND_FEATCH,DFS_QUERY_THEN_FEATCH和DFS_QUERY_AND_FEATCH.

基于Elasticsearch实现搜索推荐

- - GinoBeFunny
在 基于Elasticsearch实现搜索建议一文中我们曾经介绍过如何基于Elasticsearch来实现搜索建议,而本文是在此基础上进一步优化搜索体验,在当搜索无结果或结果过少时提供推荐搜索词给用户. 在根据用户输入和筛选条件进行搜索后,有时返回的是无结果或者结果很少的情况,为了提升用户搜索体验,需要能够给用户推荐一些相关的搜索词,比如用户搜索【迪奥】时没有找到相关的商品,可以推荐搜索【香水】、【眼镜】等关键词.

基于Elasticsearch实现搜索建议

- - GinoBeFunny
搜索建议是搜索的一个重要组成部分,一个搜索建议的实现通常需要考虑建议词的来源、匹配、排序、聚合、关联的文档数和拼写纠错等,本文介绍一个基于Elasticsearch实现的搜索建议. 电商网站的搜索是最基础最重要的功能之一,搜索框上面的良好体验能为电商带来更高的收益,我们先来看看淘宝、京东、亚马逊网站的搜索建议.

【翻译】用 elasticsearch 和 elasticsearch 为数十亿次客户搜索提供服务

- - IT技术博客大学习
标签:   elasticsearch   elasticsearch   搜索.    原文地址: http://www.elasticsearch.org/blog/using-elasticsearch-and-logstash-to-serve-billions-of-searchable-events-for-customers/.

Elasticsearch分布式搜索架构原理 | Elasticsearch权威指南(中文版)

- -
在继续之前,我们将绕道讲一下搜索是如何在分布式环境中执行的. 它比我们之前讲的基础的增删改查(create-read-update-delete,CRUD)请求要复杂一些. 本章的信息只是出于兴趣阅读,使用Elasticsearch并不需要理解和记住这里的所有细节. 阅读这一章只是增加对系统如何工作的了解,并让你知道这些信息以备以后参考,所以别淹没在细节里.

开源搜索引擎评估:lucene sphinx elasticsearch

- - 鲁塔弗的博客
lucene系,java开发,包括 solr和 elasticsearch. sphinx,c++开发,简单高性能. 搜索引擎程序这个名称不妥当,严格说来应该叫做 索引程序(indexing program),早期主要用来做中文全文搜索,但是随着互联网的深入普及,各家网站规模越来越大,索引程序在 优化网站架构上发挥了更大的作用: 替代mysql数据库 内置的索引.

使用elasticsearch+simple_flow搭建实时日志搜索系统

- - ITeye博客
    在实际的系统中,我们经常会进行分布式的系统部署,但是这样会导致一个问题,系统日志也被分散开了,导致根据日志进行错误定位不太方便,所以,利用simple_flow实时流的特点,再配合elasticsearch建立索引,搭配构建一个实时日志搜索系统.具体流程图如下:. 1.启动elasticsearch, 这个参考官方文档  http://www.elasticsearch.org/.