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:使用 Elasticsearch 进行语义搜索

- - 掘金 后端
在数字时代,搜索引擎在通过浏览互联网上的大量可用信息来检索数据方面发挥着重要作用. 此方法涉及用户在搜索栏中输入特定术语或短语,期望搜索引擎返回与这些确切关键字匹配的结果. 虽然关键字搜索对于简化信息检索非常有价值,但它也有其局限性. 主要缺点之一在于它对词汇匹配的依赖. 关键字搜索将查询中的每个单词视为独立的实体,通常会导致结果可能与用户的意图不完全一致.

[Elasticsearch] 分布式搜索

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

ElasticSearch入门-搜索如此简单

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

Elasticsearch搜索类型(query type)详解

- - ITeye博客
欢迎发送邮件至 [email protected]. 请支持原创 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数据库 内置的索引.