参考官网 Elasticsearch Reference [7.10] » Query DSL » Geo queries
@[TOC]
一、准备数据
1.1、geo_point
ES中特有的类型geo_point
,用来存储地图类型,某平台外卖。快递体现的配送人员距离你多少米,就是这个数据类型做出来的。
1.2、新建索引map
PUT /map
{
"settings": {
"number_of_replicas": 3,
"number_of_shards": 5
}
, "mappings": {
"properties": {
"name":
{
"type": "text"
}
,"location":
{
"type": "geo_point"
}
}
}
}
1.3、添加数据
PUT /map/_doc/1
{
"name":"天安门",
"location":
{
"lon":116.403981,
"lat":39.914492
}
}
PUT /map/_doc/2
{
"name":"海淀公园",
"location":
{
"lon":116.302509,
"lat":39.991152
}
}
PUT /map/_doc/3
{
"name":"北京动物园",
"location":
{
"lon":116.343184,
"lat":39.947468
}
}
二、ES的地图检索方式
ES支持的地图检索方式有以下几种;
geo_distance
geo_bounding_box
geo_polygon
2.1、geo_distance
:直线距离检索,如给定点A,要求返回地图上距离点A三千米的商家(点外卖场景)
2.1.1、查找索引内距离北京站(116.433733,39.908404)3000米内的点
geo_distance
涉及的参数如下
- location:确定一个点;
- distance:确定一个半径,单位米
- distance_type:确定一个图形的类型,一般是圆形,arc
2.1.1.1、Restful 代码
POST /map/_search
{
"query": {
"geo_distance":
{
"location":
{
"lon":116.433733
,"lat":39.908404
},
"distance":3000,
"distance_type":"arc"
}
}
}
2.1.1.2、java 代码实现
package com.chb.test;
import com.chb.utils.ESClient;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.junit.Test;
import java.io.IOException;
public class GeoDemo {
RestHighLevelClient client = ESClient.getClient();
String index = "map";
@Test
public void geoDistance() throws IOException {
// 1、SearchRequest对象
SearchRequest searchRequest = new SearchRequest(index);
// 2、指定查询参数
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.geoDistanceQuery("location").distance("3000").point(39.908404,116.433733));
// 将条件添加到request对象
searchRequest.source(searchSourceBuilder);
// 3、执行
SearchResponse resp = client.search(searchRequest, RequestOptions.DEFAULT);
// 4、输出
for (SearchHit hit : resp.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
}
}
2.2、geo_bounding_box
:以两个点确定一个矩形,获取在矩形内的全部数据
2.2.1、geo_bounding_box
涉及的参数如下
top_left
: 左上角的矩形起始点经纬度;bottom_right
: 右下角的矩形结束点经纬度
2.2.2、查找索引内位于中央民族大学(116.326943,39.95499)以及京站(116.433733,39.908404)矩形的点
2.2.2.1、RESTful 代码
POST /map/_search
{
"query": {
"geo_bounding_box": {
"location": {
"top_left": {
"lon": 116.326943,
"lat": 39.95499
},
"bottom_right": {
"lon": 116.433446,
"lat": 39.908737
}
}
}
}
}
2.2.2.2、java 代码
// 2、指定查询参数
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// =======改变的代码========
searchSourceBuilder.query(QueryBuilders.geoBoundingBoxQuery("location").setCorners(39.95499,116.326943,39.908737,116.433446));
// =====================
// 将条件添加到request对象
searchRequest.source(searchSourceBuilder);
2.3、geo_polygon
:以多个点,确定多边形,获取多边形内的全部数据
2.3.1、geo_polygon涉及的参数如下
points
:是个数组,存储多变形定点的经纬度,每个点用大括号包起来
2.3.2、查找索引内位于西苑桥(116.300209,40.003423),巴沟山水园(116.29561,39.976004)以及北京科技大学(116.364528,39.996348)三角形内的点
2.3.2.1、RESTful 代码
POST /map/_search
{
"query": {
"geo_polygon": {
"location": {
"points": [
{
"lon": 116.29561,
"lat": 39.976004
},
{
"lon": 116.364528,
"lat": 39.996348
},
{
"lon": 116.300209,
"lat": 40.003423
}
]
}
}
}
}
2.3.2.2、java 代码
// 2、指定查询参数
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// =======改变的代码========
List points=new ArrayList();
//注意java里面是纬经度的顺序,不要搞反了
points.add(new GeoPoint(39.976004,116.29561));
points.add(new GeoPoint(39.996348,116.364528));
points.add(new GeoPoint(40.003423,116.300209));
searchSourceBuilder.query(QueryBuilders.geoPolygonQuery("location", points));
// =====================
// 将条件添加到request对象
searchRequest.source(searchSourceBuilder);