当前位置: 首页 > 工具软件 > Spot Search > 使用案例 >

Elasticsearch 计算距离

丰岳
2023-12-01

总结

Elasticsearch 计算并返回距离一共有两种方法:sortscript_fields

环境概述

  • CentOS 7.6
  • Elasticsearch 7.10

创建索引

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
  }
}

索引数据

PUT /scenic_spot/_doc/1
{
  "id": 1,
  "name": "恭王府景区",
  "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": "八达岭长城",
  "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
}

响应结果如下,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) 函数,后来被废弃。现在只支持 arcDistance(lat, lon) 函数:计算两点距离,单位为:m。响应结果如下,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" : "八达岭长城",
          "pin" : {
            "location" : {
              "lat" : 40.361375,
              "lon" : 116.019809
            }
          }
        },
        "fields" : {
          "distance" : [
            391.55015001577397
          ]
        }
      }
    ]
  }
}

 类似资料: