Elasticsearch 計(jì)算距離,根據(jù)距離排序,地理點(diǎn)和地理多邊形范圍查找
總結(jié)
Elasticsearch 計(jì)算并返回距離一共有兩種方法:sort 和 script_fields
環(huán)境概述
- CentOS 7.6
- Elasticsearch 7.10
創(chuàng)建索引
PUT /scenic_spot
{
"mappings": {
"properties": {
"id": {
"type": "keyword"
},
"name": {
"type": "text"
},
"pin": {
"properties": {
"location": {
"type": "geo_point"
}
}
}
}
},
"settings": {
"number_of_replicas": 3,
"number_of_shards": 3
}
}
索引數(shù)據(jù)
PUT /scenic_spot/_doc/1
{
"id": 1,
"name": "恭王府景區(qū)",
"pin": {
"location": {
"lat": 31.007925,
"lon": 103.607572
}
}
}
PUT /scenic_spot/_doc/2
{
"id": 2,
"name": "故宮博物院",
"pin": {
"location": {
"lat": 39.917248,
"lon": 116.397176
}
}
}
PUT /scenic_spot/_doc/3
{
"id": 3,
"name": "天壇公園",
"pin": {
"location": {
"lat": 39.881265,
"lon": 116.410638
}
}
}
PUT /scenic_spot/_doc/4
{
"id": 4,
"name": "頤和園",
"pin": {
"location": {
"lat": 39.991664,
"lon": 116.271966
}
}
}
PUT /scenic_spot/_doc/5
{
"id": 5,
"name": "八達(dá)嶺長城",
"pin": {
"location": {
"lat": 40.361375,
"lon": 116.019809
}
}
}
Sort 返回距離
GET /scenic_spot/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"_geo_distance": {
"pin.location": {
"lat": 38.912780578039346,
"lon": 120.18819440815733
},
"order": "asc",
"unit": "km"
}
}
],
"size": 1
}
響應(yīng)結(jié)果如下,hits 下的 sort 字段就是距離,單位:km。
{
"took" : 4,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 5,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
{
"_index" : "scenic_spot",
"_type" : "_doc",
"_id" : "3",
"_score" : null,
"_source" : {
"id" : 3,
"name" : "天壇公園",
"pin" : {
"location" : {
"lat" : 39.881265,
"lon" : 116.410638
}
}
},
"sort" : [
341.96155623680716
]
}
]
}
}
Script_fields 返回距離
GET /scenic_spot/_search
{
"query": {
"match_all": {}
},
"_source": true,
"script_fields": {
"distance": {
"script": {
"lang": "painless",
"params": {
"lat": 38.912780578039346,
"lon": 120.18819440815733
},
"source": "doc['pin.location'].arcDistance(params.lat, params.lon)/1000"
}
}
},
"size": 1
}
5.x 以前支持:distanceInKm(lat, lon) 函數(shù),后來被廢棄?,F(xiàn)在只支持 arcDistance(lat, lon) 函數(shù):計(jì)算兩點(diǎn)距離,單位為:m。響應(yīng)結(jié)果如下,hits 下的 fields.distance 字段就是距離,單位:km。
{
"took" : 3,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 5,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "scenic_spot",
"_type" : "_doc",
"_id" : "5",
"_score" : 1.0,
"_source" : {
"id" : 5,
"name" : "八達(dá)嶺長城",
"pin" : {
"location" : {
"lat" : 40.361375,
"lon" : 116.019809
}
}
},
"fields" : {
"distance" : [
391.55015001577397
]
}
}
]
}
}
地理點(diǎn)和地理多邊形范圍查找
Elasticsearch](https://so.csdn.net/so/search?q=Elasticsearch&spm=1001.2101.3001.7020) 是一個(gè)功能強(qiáng)大的搜索引擎,支持地理查詢,但并不是每個(gè)人都習(xí)慣于處理空間數(shù)據(jù)。 如果你對地理處理了解不多,或者想通過 Elasticsearch 了解地理處理,那么本文適合你。在我們的現(xiàn)實(shí)生活中,我們經(jīng)常使用的滴滴打車,美團(tuán)送餐,美國的 Uber, Lyft 打車,還有一些交友 apps 等等,它們都是使用 Elasticsearch 進(jìn)行位置搜索的例子。
地理距離查詢返回距離點(diǎn)最大距離的所有文檔,例如:Dolores 想認(rèn)識(shí)距離她約 300 米的所有人:
紅色圓圈的半徑為 300 米,我們可以看到只有 William 在圓圈內(nèi)。
讓我們來做一下 Elasticsearch 的實(shí)現(xiàn)。 首先,使用屬性 name 和 location 創(chuàng)建一個(gè) user_location 索引。
PUT user_location
{
"mappings": {
"properties": {
"name": {
"type": "text"
},
"location": {
"type": "geo_point"
}
}
}
}
location 的數(shù)據(jù)類型為 geo_point, 表示地球上的位置。 點(diǎn)具有經(jīng)度和緯度(坐標(biāo))。 你可以在官方文檔中檢查所有可接受的 geo_point 格式。
現(xiàn)在,讓我們?yōu)?William,Robert 和 Bernard 的位置創(chuàng)建文檔。我們使用 _bulk API 來導(dǎo)入數(shù)據(jù):
POST user_location/_bulk
{ "index" : { "_id" : "1" } }
{ "name" : "William", "location": "-25.443053, -49.238396" }
{ "index" : { "_id" : "2" } }
{ "name" : "Robert", "location": "-25.440173, -49.243169" }
{ "index" : { "_id" : "3" } }
{ "name" : "Bernard", "location": "-25.440262, -49.247720" }
為了說明問題的方便,我特地創(chuàng)建一個(gè)新的索引叫做 locations,它包含了 Dolores 的位置信息:
PUT locations
{
"mappings": {
"properties": {
"name": {
"type": "text"
},
"location": {
"type": "geo_point"
}
}
}
}
POST locations/_bulk
{ "index" : { "_id" : "1" } }
{ "name" : "William", "location": "-25.443053, -49.238396" }
{ "index" : { "_id" : "2" } }
{ "name" : "Robert", "location": "-25.440173, -49.243169" }
{ "index" : { "_id" : "3" } }
{ "name" : "Bernard", "location": "-25.440262, -49.247720" }
{ "index" : { "_id" : "4" } }
{ "name" : "Dolores", "location": "-25.442987, -49.239504" }
在上面的 _id 為 4 的文檔就是 Doloes 的位置信息。我們來創(chuàng)建一個(gè)叫做 locations 的索引模式:
我們打開 Maps 應(yīng)用:
我們發(fā)現(xiàn)這四個(gè)位置位于南美的某個(gè)地方。我們編輯 location 層的設(shè)置,當(dāng)我們點(diǎn)擊該位置的時(shí)候,顯示名字及 id。我們調(diào)整合適的 zoom 大?。?/p>
從上面的圖中,我們很清楚地看到每個(gè)人的相對的位置。離 Dolores 最近的就是 Willam,也就是那個(gè)被蓋著的那個(gè),接著就是 Robert。最遠(yuǎn)的就是 Bernard。請注意,我們上面的展示都是以 locations 這個(gè)索引來進(jìn)行展示的。它里面含有 Dolores。我們現(xiàn)在使用 user_location 索引來進(jìn)行搜索:
GET user_location/_search
{
"query": {
"bool": {
"filter": {
"geo_distance": {
"distance": "300m",
"location": "-25.442987, -49.239504"
}
}
}
}
}
在上面,我們針對 Dolores 來進(jìn)行搜索。顯示的結(jié)果是:
{
"took" : 55,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.0,
"hits" : [
{
"_index" : "user_location",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.0,
"_source" : {
"name" : "William",
"location" : "-25.443053, -49.238396"
}
}
]
}
}
也就是說在 Dolores 方圓 300m 之內(nèi),只有 William。如果我們把半徑增加到 600 m,那么我可以看到 Robert:
GET user_location/_search
{
"query": {
"bool": {
"filter": {
"geo_distance": {
"distance": "600m",
"location": "-25.442987, -49.239504"
}
}
}
}
}
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 0.0,
"hits" : [
{
"_index" : "user_location",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.0,
"_source" : {
"name" : "William",
"location" : "-25.443053, -49.238396"
}
},
{
"_index" : "user_location",
"_type" : "_doc",
"_id" : "2",
"_score" : 0.0,
"_source" : {
"name" : "Robert",
"location" : "-25.440173, -49.243169"
}
}
]
}
}
地理多邊形查詢可獲取多邊形內(nèi)的文檔。
“多邊形是具有直邊的封閉形狀。 矩形,三角形,六邊形和八邊形都是多邊形的例子?!?/p>
它由點(diǎn)列表表示。 兩點(diǎn)之間最接近的路徑是一條直線。 多邊形的起點(diǎn)和終點(diǎn)均相同。 在下面的圖上檢查下面的植物園多邊形。
請注意,Elasticsearch 上的地理查詢會(huì)檢查文檔的 geo_point 屬性是否在多邊形內(nèi)。 例:Dolores 想知道植物園內(nèi)的每個(gè)人。
文章來源:http://www.zghlxwxcb.cn/news/detail-705978.html
GET user_location/_search
{
"query": {
"bool": {
"filter": {
"geo_polygon": {
"location": {
"points": [
"-25.44373,-49.24248",
"-25.44297,-49.24230",
"-25.44177,-49.23642",
"-25.43961,-49.23822",
"-25.43991,-49.23781",
"-25.44170,-49.23647",
"-25.44210,-49.23586",
"-25.44218,-49.23506",
"-25.44358,-49.23491",
"-25.44406,-49.24139",
"-25.44373,-49.24248"
]
}
}
}
}
}
}
上面的搜索返回的結(jié)果:文章來源地址http://www.zghlxwxcb.cn/news/detail-705978.html
{
"took" : 15,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.0,
"hits" : [
{
"_index" : "user_location",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.0,
"_source" : {
"name" : "William",
"location" : "-25.443053, -49.238396"
}
}
]
}
}
到了這里,關(guān)于Elasticsearch計(jì)算距離,根據(jù)距離排序,地理點(diǎn)和地理多邊形范圍查找的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!