ElasticSearch实现基于经纬度的附近搜索

标签: 分享 | 发表时间:2020-08-04 12:43 | 作者:标点符
出处:https://www.biaodianfu.com

ElasticSearch除了支持文本检索外,还支持地理信息检索。它主要支持两种类型的地理查询:一种是地理点(geo_point),即经纬度查询,另一种是地理形状查询(geo_shape),即支持点、线、圈、多边形查询等。

ElasticSearch实现经纬度附近搜索

1、创建映射(mapping)

import requests
import json
attractions_url = "http://localhost:9200/attractions?include_type_name=true"
data = {
    "mappings": {
        "hotel": {
            "properties": {
                "name": {
                    "type": "text"
                },
                "location": {
                    "type": "geo_point"
                }
            }
        }
    }
}

json_data = json.loads(json.dumps(data))
r = requests.put(url=attractions_url, json=json_data)
print(r.status_code)
print(r.text)

对于某些特殊的查询,例如矩形范围查询,可以通过分别对lat和lon进行索引以提高查询速度。因为矩形范围的查询完全可以先通过lat过滤,再通过lon过滤。要实现此功能只需在location节点下添加”lat_lon”: true即可。

2、添加数据(插入文档)

import requests
import json
import pandas as pd
f = pd.read_csv("data.csv")
for index, row in df.iterrows():
    url = "http://localhost:9200/attractions/hotel/{0}".format(index)
    data = {"name": str(int(row['hotel_id'])), "location": {"lat": row['lat'], "lon": row['lon']}}
    json_data = json.loads(json.dumps(data))
    r = requests.put(url, json=json_data)

插入文档时,有三种格式的属性可以被映射为 geo_point 类型:

  • string:格式为lat,lon
  • double []:格式为[lon, lat]
  • json:格式为{ “lat”: lat, “lon”: lon}

注意:数组格式是 lon 在前,lat 在后,而字符串格式正好相反。

3、查询

Elasticsearch 的地理位置查询,实际是使用过滤器对所有文档进行过滤。它支持以下四种查询方式:

  • geo_bounding_box:查询矩形范围内的点
  • geo_distance:查询中心点距离范围内的点
  • geo_distance_range:查询中心点最小距离和最大距离之间的点
  • geo_polygon:查询多边形范围内的点(不推荐使用)

以下为通过中心点距离范围内的示例:

import requests
import json
url = "http://localhost:9200/attractions/hotel/_search"
lat, lon = 34.514020, 113.191598
data = {
    "query": {
        "bool": {
            "must": {
                "match_all": {}
            },
            "filter": {
                "geo_distance": {
                    "distance": "10km",
                    "location": {
                        "lat": lat,
                        "lon": lon
                    }
                }
            }
        }
    }, "sort": [
        {
            "_geo_distance": {
                "location": [
                    {
                        "lat": lat,
                        "lon": lon
                    }
                ],
                "unit": "m",
                "distance_type": "arc",
                "order": "asc",
                "validation_method": "STRICT"
            }
        }
    ]
}
json_data = json.loads(json.dumps(data))
r = requests.get(url, json=json_data)

除了中心点和距离,我们还需要指定计算距离的方式,每种方式对应着不同的精度和计算速度,常用的有三种:

  • arc:最慢但最精确的是 arc 计算方式,这种方式把世界当作球体来处理。不过这种方式的精度有限,因为这个世界并不是完全的球体。
  • plane:plane 计算方式把地球当成是平坦的,这种方式快一些但是精度略逊。在赤道附近的位置精度最好,而靠近两极则变差。
  • sloppy_arc:如此命名,是因为它使用了 Lucene的SloppyMath 类。这是一种用精度换取速度的计算方式,它使用 Haversine formula 来计算距离。它比 arc 计算方式快 4 到 5 倍,并且距离精度达9%。这也是默认的计算方式。

对于大部分应用来说,plane的精度已经足够了,并且速度是最快的,所以推荐使用它。

ElasticSearch按距离打分的配置

ElasticSearch除了按照距离排序外,还支持按距离打分并且与其他评分一起应用。

有三种衰减函数:linear 、 exp 和 gauss (线性、指数和高斯函数),它们可以操作数值、时间以及经纬度地理坐标点这样的字段。所有三个函数都能接受以下参数:

  • Origin:中心点 或字段可能的最佳值,落在原点 origin 上的文档评分 _score 为满分0。
  • Scale:衰减率,即一个文档从原点 origin 下落时,评分 _score 改变的速度。
  • Decay:从原点 origin 衰减到 scale 所得的评分 _score ,默认值为5 。
  • Offset:以原点 origin 为中心点,为其设置一个非零的偏移量 offset 覆盖一个范围,而不只是单个原点。在范围 -offset <= origin <= +offset 内的所有评分 _score 都是0 。

这三个函数的唯一区别就是它们衰减曲线的形状,用图来说明会更为直观:

gauss

$$S(doc) = \exp(-\frac{\max(0,|\text{fieldvalue}_{doc}-\text{origin}|-\text{offset})^2}{2\sigma ^2})$$

其中:

$$\sigma ^2=-\frac{\text{scale}^2}{2\cdot \ln(\text{decay})}$$

exp

$$S(doc) =  \exp(\lambda \cdot max(0,|\text{fieldvalue}_{doc}-\text{origin}|-\text{offset}))$$

其中:

$$\lambda  = \frac{\ln(\text{scale})}{\text{scale}}$$

linear

$$S(doc) =  \max(\frac{s-\max(0,|\text{fieldvalue}_{doc}-\text{origin}|-\text{offset})}{s},0)$$

其中:

$$s = \frac{\text{scale}}{1.0-\text{decay}}$$

参考连接:

相关 [elasticsearch 经纬度 搜索] 推荐:

ElasticSearch实现基于经纬度的附近搜索

- - 标点符
ElasticSearch除了支持文本检索外,还支持地理信息检索. 它主要支持两种类型的地理查询:一种是地理点(geo_point),即经纬度查询,另一种是地理形状查询(geo_shape),即支持点、线、圈、多边形查询等. ElasticSearch实现经纬度附近搜索. 1、创建映射(mapping).

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数据库 内置的索引.