1 pom文件,yml 文件设置,就不说了
2 pojo文件
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.*;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import java.time.LocalDateTime;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(indexName = "scenie", shards = 1, replicas = 1)
public class Scenie {
@Id
private Long id;
@Field(name = "name", type = FieldType.Text, analyzer = "ik_max_word")
private String name;
@Field(name = "address", type = FieldType.Text, analyzer = "ik_max_word")
private String address;
@Field(name = "city", type = FieldType.Keyword)
private String city;
@Field(name = "area", type = FieldType.Keyword)
private String area;
//****** elasticsearch geo坐标 类型 *****
@GeoPointField
private GeoPoint location;
//日期类型
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@Field(name = "createTime", format = DateFormat.custom, type = FieldType.Date, pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
}
3 测试类
import cn.haiwang.es_test_1.pojo.Scenie;
import org.elasticsearch.common.geo.GeoDistance;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.GeoBoundingBoxQueryBuilder;
import org.elasticsearch.index.query.GeoDistanceQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.GeoDistanceSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.util.LinkedHashMap;
import java.util.List;
@RestController
public class Controller_2 {
@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;
/**
* 添加
*/
@RequestMapping("/add")
public void add() {
Double lat = 39.948054;
Double lon = 116.391411;
GeoPoint geoPoint = new GeoPoint(lat, lon);
Scenie scenie = new Scenie(1L, "绿地万怡酒店", "沪宜公路3101号", "上海", "嘉定新城", geoPoint, LocalDateTime.now());
elasticsearchRestTemplate.save(scenie);
}
/**
* geo_bounding_box 矩形过滤 (左上角 一个坐标,右下角一个坐标,画个距形过滤)
*
* @return
*/
@RequestMapping("/find_byBoundingBox")
public Object find_byBoundingBox(@RequestParam(defaultValue = "0") Integer pageIndex,
@RequestParam(defaultValue = "10") Integer pageSize) {
//分页信息
PageRequest pageRequest = PageRequest.of(pageIndex, pageSize);
//矩形过滤
GeoBoundingBoxQueryBuilder geoBoundingBoxQueryBuilder = QueryBuilders.geoBoundingBoxQuery("location")
.setCorners(39.968263, 116.315444,
39.870426, 116.464347);
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder()
//查询
.withQuery(geoBoundingBoxQueryBuilder)
//分页
.withPageable(pageRequest);
SearchHits<Scenie> scenie = elasticsearchRestTemplate.search(nativeSearchQueryBuilder.build(), Scenie.class, IndexCoordinates.of("scenie"));
List<SearchHit<Scenie>> searchHits = scenie.getSearchHits();
PageImpl<SearchHit<Scenie>> searchHits1 = new PageImpl<>(searchHits, pageRequest, scenie.getTotalHits());
return searchHits1;
}
/**
* geo_distance 距离查询(圆形过滤),从一个点坐标,指定距离画个画过滤
*
* @param pageIndex
* @param pageSize
* @param distance 想查看周边几公里的信息
* @return
*/
@RequestMapping("/find_byDistance")
public Object find_byDistance(@RequestParam(defaultValue = "0") Integer pageIndex,
@RequestParam(defaultValue = "10") Integer pageSize,
@RequestParam(defaultValue = "2") Double distance) {
//分页信息
PageRequest pageRequest = PageRequest.of(pageIndex, pageSize);
//假如 查询 这个坐标 ,周边几 km的信息
Double lat = 39.948054;
Double lon = 116.391411;
// 按距离升序
GeoDistanceSortBuilder distanceSortBuilder = new GeoDistanceSortBuilder("location", lat, lon);
distanceSortBuilder.order(SortOrder.ASC);
distanceSortBuilder.unit(DistanceUnit.KILOMETERS);
以某点为中心,搜索指定范围
GeoDistanceQueryBuilder distanceQueryBuilder = QueryBuilders.geoDistanceQuery("location")
.point(lat, lon)
// 定义查询单位:公里
.distance(distance, DistanceUnit.KILOMETERS);
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
//查询
nativeSearchQueryBuilder.withQuery(distanceQueryBuilder);
//分页
nativeSearchQueryBuilder.withPageable(pageRequest);
//排序
nativeSearchQueryBuilder.withSort(distanceSortBuilder);
SearchHits<Scenie> jingqu = elasticsearchRestTemplate.search(nativeSearchQueryBuilder.build(), Scenie.class, IndexCoordinates.of("scenie"));
List<SearchHit<Scenie>> searchHits = jingqu.getSearchHits();
LinkedHashMap<String, String> hashMap = new LinkedHashMap<>();
searchHits.stream().forEach(searchHit -> {
String name = searchHit.getContent().getName();
//注意:没有指定排序,这里为null
String px = searchHit.getSortValues().get(0).toString();
//计算两点间的距离
double calculate = GeoDistance.ARC.calculate(lat, lon,
searchHit.getContent().getLocation().getLat(),
searchHit.getContent().getLocation().getLon(), DistanceUnit.KILOMETERS);
hashMap.put(name, "排序里的距离:" + px + "------距离(算法方法算的):" + calculate);
});
return hashMap;
}
}
附录:elasticsearch 索引创建
PUT scenie
{
"mappings": {
"properties": {
"id": {
"type": "long"
},
"address": {
"type": "text",
"analyzer": "ik_max_word"
},
"area": {
"type": "keyword"
},
"city": {
"type": "keyword"
},
"location": {
"type": "geo_point"
},
"createTime": {
"type": "date",
"format": [
"yyyy-MM-dd HH:mm:ss"
]
},
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
},
"name_tishi": {
"type": "completion",
"analyzer": "pinyin_analyzer",
"preserve_separators": true,
"preserve_position_increments": true,
"max_input_length": 50
}
},
"analyzer": "ik_max_word"
}
}
},
"settings": {
"index": {
"analysis": {
"analyzer": {
"pinyin_analyzer": {
"tokenizer": "my_pinyin"
}
},
"tokenizer": {
"my_pinyin": {
"lowercase": "true",
"keep_original": "true",
"remove_duplicated_term": "true",
"keep_separate_first_letter": "false",
"type": "pinyin",
"limit_first_letter_length": "16",
"keep_full_pinyin": "true"
}
}
}
}
}
}