说明
给定圆心点坐标、半径,查询落在该圆的点
实体类
package es.entity;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.GeoPointField;
import org.elasticsearch.common.geo.GeoPoint;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import org.springframework.data.elasticsearch.annotations.GeoPointField;
@Document(indexName = "meituan_v1", shards = 1, replicas = 0)
public class Meituan {
@Id
private String id;
@Field(type = FieldType.Keyword)
private String name;
@GeoPointField
private GeoPoint location;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public GeoPoint getLocation() {
return location;
}
public void setLocation(GeoPoint location) {
this.location = location;
}
@Override
public String toString() {
return "Meituan{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", location=" + location +
'}';
}
}
地理范围查询
service类
package day1.service;
import day1.entity.Meituan;
import org.elasticsearch.common.geo.GeoDistance;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.GeoDistanceQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.GeoDistanceSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.annotation.Resource;
@Service
public class ESMeituanSrvImpl {
@Resource
private ElasticsearchRestTemplate template;
/**
* 地理范围查询
*
* @param lat
* @param lon
* @param distance
* @return
*/
public SearchHits<Meituan> geo(double lat, double lon, double distance){
//构建地理查询条件
GeoDistanceQueryBuilder builder =
QueryBuilders
.geoDistanceQuery("location")//查询字段
.point(lat, lon)//设置圆心点经纬度
.distance(distance, DistanceUnit.KILOMETERS)//设置半径距离和单位(千米)
.geoDistance(GeoDistance.PLANE);// 使用平面算法
//构建排序
GeoDistanceSortBuilder sortBuilder =
SortBuilders.geoDistanceSort("location",lat,lon)//设置参照点经纬度
.point(lat, lon)
.unit(DistanceUnit.KILOMETERS) // 返回结果有sort,表示距离,这个单位就是距离单位
.order(SortOrder.ASC);//排序方式
//构造查询条件
NativeSearchQuery nativeSearchQuery =
new NativeSearchQueryBuilder()
.withFilter(builder)
.withSort(sortBuilder)
.build();
SearchHits<Meituan> shs = template.search(nativeSearchQuery, Meituan.class);
return shs;
}
}
测试类
在 test 目录下创建类,如下图:
package test;
import day1.Main;
import day1.entity.Meituan;
import day1.service.ESMeituanSrvImpl;
import org.elasticsearch.common.unit.DistanceUnit;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Main.class)
public class TestESMeituanSrvImpl {
@Resource
private ESMeituanSrvImpl srv;
@Test
public void geo(){
SearchHits<Meituan> shs = srv.geo(77, 35, 200);
for(SearchHit<Meituan> item:shs){
Meituan meituan=item.getContent();
List<Object> sortValues = item.getSortValues();
if(sortValues!=null && sortValues.size()>0){
double d=(Double)sortValues.get(0);//距离
System.out.print("距离:"+d+" "+ DistanceUnit.KILOMETERS+ "--");
}
System.out.println(meituan);
}
}
}
模糊条件 + 地理查询
通配符实现模糊查询店家名称,并在距离圆心点200km的范围的店家
service
在上面 service 类中加入下面代码:
public SearchHits<Meituan> geo2(String keyword, double lat, double lon, double distance){
//通配符模糊查询店家名称
WildcardQueryBuilder nameQuery = QueryBuilders.wildcardQuery("name", "*" + keyword + "*");
//构建地理查询条件
GeoDistanceQueryBuilder geoBuilder =
QueryBuilders.geoDistanceQuery("location")//查询字段
.point(lat, lon)//设置圆心点经纬度
.distance(distance, DistanceUnit.KILOMETERS)//设置半径距离和单位(千米)
.geoDistance(GeoDistance.PLANE);// 使用平面算法
//构建bool查询
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery()
.must(nameQuery)
.must(geoBuilder);
//构建排序
GeoDistanceSortBuilder sortBuilder =
SortBuilders.geoDistanceSort("location",lat,lon)//设置参照点经纬度
.point(lat, lon)
.unit(DistanceUnit.KILOMETERS) // 返回结果有sort,表示距离,这个单位就是距离单位
.order(SortOrder.ASC);//排序方式
//构造查询条件
NativeSearchQueryBuilder nativeSearchQueryBuilder =
new NativeSearchQueryBuilder()
.withFilter(boolQuery)
.withSort(sortBuilder);
SearchHits<Meituan> shs = template.search(nativeSearchQueryBuilder.build(), Meituan.class);
return shs;
}
测试
在上面的测试类中增加下面代码:
@Test
public void geo2(){
SearchHits<Meituan> shs = srv.geo2("面",77,35,120);
// SearchHits<Meituan> shs = srv.geo2("面",77,35,200);
for(SearchHit<Meituan> item:shs){
Meituan meituan=item.getContent();
List<Object> sortValues = item.getSortValues();
if(sortValues!=null && sortValues.size()>0){
double d=(Double)sortValues.get(0);//距离
System.out.print("距离:"+d+" "+DistanceUnit.KILOMETERS+"--");
}
System.out.println(meituan);
}
}
半径不同,查询出的店家也不同

