DTO
import lombok.Data;
/**
* @params 写入ES的一些通用方法
* @Description
* @Author Hc
* @CreateUser: Hc
* @CreateDate 2021/12/1 16:30
* @Version 1.0
* @Return
**/
@Data
public class UnitToEsDTO{
/**
* 通用ID
*/
private String id;
/**
* 经度
*/
private Double longitude;
/**
* 维度
*/
private Double latitude;
/**
* 地址
*/
private String address;
/**
* 距离
*/
private String distance;
/**
* 类型
* 1 企业
*/
private Integer type;
private Double[] location;
private String userId;
private Integer start;
private Integer limit;
}
地理位置搜索方法一
public List<UnitToEsDTO> queryUnitByEs(UnitToEsDTO unitToEsDTO){
List<UnitToEsDTO> list = new ArrayList<>();
List<UnitToEsDTO> resultlist = new ArrayList<>();
try{
// 定义搜索请求和索引
SearchRequest searchRequest = new SearchRequest(ESConstant.UNIT_GEOGRAPHICAL_POSITION_INDEX);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 分页 es好像是没有自带的PageHelp 变成我们所需的分页
if(unitToEsDTO.getStart()!=null&&unitToEsDTO.getLimit()!=null){
Integer startPage = (unitToEsDTO.getStart()-1)*unitToEsDTO.getLimit();
Integer limitPage = unitToEsDTO.getLimit();
searchSourceBuilder.from(startPage);
searchSourceBuilder.size(limitPage);
}
// 构造查询和过滤数据
searchSourceBuilder.query(
// 构造布尔查询
QueryBuilders.boolQuery()
// 查询语句
.must(
//对type进行过滤 可以在这里筛选一些不需要的
QueryBuilders.matchQuery("type", unitToEsDTO.getType())
//不过滤
//QueryBuilders.matchAllQuery()
)
// 过滤语句
.filter(
// name 是过滤的字段
QueryBuilders.geoDistanceQuery("location")
// 在distance km之内 km 也可以设置为m cm等
.distance(unitToEsDTO.getDistance(), DistanceUnit.KILOMETERS)
// 以那个点为中心
.geoDistance(GeoDistance.ARC)
// 设置经纬度
.point(unitToEsDTO.getLatitude(), unitToEsDTO.getLongitude())
)
);
// 排序
searchSourceBuilder.sort(
// 不同的类型使用不同的SortBuilder
new GeoDistanceSortBuilder("location", unitToEsDTO.getLatitude(), unitToEsDTO.getLongitude())
// 升序
.order(SortOrder.ASC)
.unit(DistanceUnit.METERS)
.geoDistance(GeoDistance.ARC)
);
searchRequest.source(searchSourceBuilder);
SearchResponse search =client.search(searchRequest,RequestOptions.DEFAULT);
SearchHit[] hits=search.getHits().getHits();
if(unitToEsDTO.getType()==1||unitToEsDTO.getType()==2){
for(SearchHit hit: hits){
UnitToEsDTO unitToEsDTOResult=JSONObject.parseObject(hit.getSourceAsString(),UnitToEsDTO.class);
list.add(unitToEsDTOResult);
}
for(UnitToEsDTO unitToEsDTOTemp: list){
Long id=Long.parseLong(unitToEsDTOTemp.getId());
//去表里查询一下 有的返回没有的不返回 懒得做删除 所以校验了一下
UnitExtendEntity unitExtendEntity=unitExtendMapper.selectByExtendId(id);
if(!StringUtils.isEmpty(unitExtendEntity)){
// 也可以 add unitExtendEntity 看需求
resultlist.add(unitToEsDTOTemp);
}
}
}else {
log.error("暂无其它类型 看如果有别的也做同样操作");
}
}catch(Exception ex){
log.error("出现异常,参数是{}",JSONObject.toJSONString(unitToEsDTO));
log.error("出现异常",ex);
}
return resultlist;
}
方法二
好像这个不太准确
public List<EleTransformer> queryTransformers(String space,String userId,String dataFrom,EleTransformer eleTransformer){
List<EleTransformer> list = new ArrayList<>();
List<EleTransformer> resultlist = new ArrayList<>();
try{
GeoDistanceQueryBuilder geoDistanceQueryBuilder = QueryBuilders.geoDistanceQuery("location")
.distance(eleTransformer.getDistance()).point(new GeoPoint(eleTransformer.getLatitude(), eleTransformer.getLongitude()));
// 通过SearchSourceBuilder构建搜索参数
SearchSourceBuilder builder = new SearchSourceBuilder();
BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
boolBuilder.must(geoDistanceQueryBuilder);
builder.query(boolBuilder);
// 距离sort 排序
GeoDistanceSortBuilder geoDistanceSortBuilder = SortBuilders.geoDistanceSort("location",
new GeoPoint(eleTransformer.getLatitude(), eleTransformer.getLongitude()));
// 升序排序 距离最近的排在最前面
geoDistanceSortBuilder.order(SortOrder.ASC);
// 设置排序参数
builder.sort(geoDistanceSortBuilder);
SearchRequest searchRequest = new SearchRequest(ESConstant.SITE_GEOGRAPHICAL_POSITION_INDEX);
searchRequest.source(builder);
// List<EleTransformerDTO> resultList = new ArrayList<>();
SearchResponse search =client.search(searchRequest,RequestOptions.DEFAULT);
SearchHit[] hits=search.getHits().getHits();
for (SearchHit hit : hits) {
EleTransformer eleTransformers=JSONObject.parseObject(hit.getSourceAsString(),EleTransformer.class);
list.add(eleTransformers);
}
for (EleTransformer ele:list) {
//去站点表里查询一下 有的返回没有的不返回
Long siteId =Long.parseLong(ele.getId()) ;
//判断该站点id是否在库里是否存在
int siteCou = sxelesiteMapper.querySiteIsExistsById(siteId);
if (siteCou>0){
resultlist.add(ele);
}
}
}catch(Exception ex){
log.error("出现异常,参数是{}",JSONObject.toJSONString(eleTransformer));
log.error("出现异常",ex);
}
return resultlist;
}
修改
我这里修改和插入可能是一个接口 所以做了判断
/**
*修改
*/
public void updateToEs(UnitToEsDTO unitToEsDTO){
try{
Map<String,Object> stringObjectMap=CopyBeanUtils.bean2Map(unitToEsDTO);
// 根据类型判断id 如果不是多个type 可以忽略这些
String esId = unitToEsDTO.getId()+"unknow";
if(unitToEsDTO.getType()==1){
esId = unitToEsDTO.getId();
}else if(unitToEsDTO.getType()==2){
esId = unitToEsDTO.getId()+"euq";
}
// 查询是否存在
GetRequest request = new GetRequest(ESConstant.UNIT_GEOGRAPHICAL_POSITION_INDEX,esId);
boolean exists=client.exists(request,RequestOptions.DEFAULT);
// 存在更新
if(exists){
// 根据id更新
UpdateRequest updateRequest = new UpdateRequest(ESConstant.UNIT_GEOGRAPHICAL_POSITION_INDEX,esId);
updateRequest.doc(stringObjectMap,XContentType.JSON);
client.update(updateRequest,RequestOptions.DEFAULT);
}else {//不存在插入
saveToEs(unitToEsDTO);
}
}catch(IOException e){
e.printStackTrace();
}
}
插入
这里的CopyBeanUtils.bean2Map 去文章里找吧 各种utils
/**
*插入
*/
public void saveToEs(UnitToEsDTO unitToEsDTO){
try{
Map<String,Object> stringObjectMap=CopyBeanUtils.bean2Map(unitToEsDTO);
IndexRequest indexRequest = new IndexRequest(ESConstant.UNIT_GEOGRAPHICAL_POSITION_INDEX).source(stringObjectMap,XContentType.JSON);
//unitToEsDTO的id将作为 es的id插入 方便以后更新
if(unitToEsDTO.getType()==1){
indexRequest.id(unitToEsDTO.getId());
}else if(unitToEsDTO.getType()==2){
indexRequest.id(unitToEsDTO.getId()+"equ");
}else {
indexRequest.id(unitToEsDTO.getId()+"unknow");
}
client.index(indexRequest,RequestOptions.DEFAULT);
}catch(IOException e){
e.printStackTrace();
}
}
删除
DeleteRequest request = new DeleteRequest(
"index",//索引
"doc", //类型
"1"); //id
DeleteResponse deleteResponse = client.delete(request, RequestOptions.DEFAULT);
踩坑
查询时出现报错信息
org.elasticsearch.ElasticsearchStatusException: Elasticsearch exception [type=search_phase_execution_exception, reason=all shards failed]
at org.elasticsearch.rest.BytesRestResponse.errorFromXContent(BytesRestResponse.java:177)
at org.elasticsearch.client.RestHighLevelClient.parseEntity(RestHighLevelClient.java:1793)
at org.elasticsearch.client.RestHighLevelClient.parseResponseException(RestHighLevelClient.java:1770)
at org.elasticsearch.client.RestHighLevelClient.internalPerformRequest(RestHighLevelClient.java:1527)
at org.elasticsearch.client.RestHighLevelClient.performRequest(RestHighLevelClient.java:1484)
at org.elasticsearch.client.RestHighLevelClient.performRequestAndParseEntity(RestHighLevelClient.java:1454)
at org.elasticsearch.client.RestHighLevelClient.search(RestHighLevelClient.java:970)
at com.qhdsx.apollo.module.msgcenter.es.ESTest.queryTransformers(ESTest.java:503)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
Suppressed: org.elasticsearch.client.ResponseException: method [POST], host [http://XXX:9200], URI [/test-haina-location_test/_search?pre_filter_shard_size=128&typed_keys=true&max_concurrent_shard_requests=5&ignore_unavailable=false&expand_wildcards=open&allow_no_indices=true&ignore_throttled=true&search_type=query_then_fetch&batched_reduce_size=512&ccs_minimize_roundtrips=true], status line [HTTP/1.1 400 Bad Request]
{"error":{"root_cause":[{"type":"query_shard_exception","reason":"field [location] is not a geo_point field","index_uuid":"iYrfwfgMRLm8ramVz-RbQw","index":"test-haina-location_test"}],"type":"search_phase_execution_exception","reason":"all shards failed","phase":"query","grouped":true,"failed_shards":[{"shard":0,"index":"test-haina-location_test","node":"QWcv79-xTDSp3UHYFQ4AFw","reason":{"type":"query_shard_exception","reason":"field [location] is not a geo_point field","index_uuid":"iYrfwfgMRLm8ramVz-RbQw","index":"test-haina-location_test"}}]},"status":400}
at org.elasticsearch.client.RestClient.convertResponse(RestClient.java:283)
at org.elasticsearch.client.RestClient.performRequest(RestClient.java:261)
at org.elasticsearch.client.RestClient.performRequest(RestClient.java:235)
at org.elasticsearch.client.RestHighLevelClient.internalPerformRequest(RestHighLevelClient.java:1514)
... 28 common frames omitted
详细原因
{
"error": {
"root_cause": [{
"type": "query_shard_exception",
"reason": "field [location] is not a geo_point field",
"index_uuid": "iYrfwfgMRLm8ramVz-RbQw",
"index": "test-haina-location_test"
}],
"type": "search_phase_execution_exception",
"reason": "all shards failed",
"phase": "query",
"grouped": true,
"failed_shards": [{
"shard": 0,
"index": "test-haina-location_test",
"node": "QWcv79-xTDSp3UHYFQ4AFw",
"reason": {
"type": "query_shard_exception",
"reason": "field [location] is not a geo_point field",
"index_uuid": "iYrfwfgMRLm8ramVz-RbQw",
"index": "test-haina-location_test"
}
}]
},
"status": 400
}
在数据插入之前 在kibana控制台 给该索引的location设置一下类型即可
PUT /test-haina-location_test
{
"mappings": {
"properties": {
"location": {
"type": "geo_point"
}
}
}
}
如果在数据插入后操作会报异常 可能就得迁移数据了
{
"error" : {
"root_cause" : [
{
"type" : "resource_already_exists_exception",
"reason" : "index [test-haina-location_test/iYrfwfgMRLm8ramVz-RbQw] already exists",
"index_uuid" : "iYrfwfgMRLm8ramVz-RbQw",
"index" : "test-haina-location_test"
}
],
"type" : "resource_already_exists_exception",
"reason" : "index [test-haina-location_test/iYrfwfgMRLm8ramVz-RbQw] already exists",
"index_uuid" : "iYrfwfgMRLm8ramVz-RbQw",
"index" : "test-haina-location_test"
},
"status" : 400
}