问题使用elasticsearch 默认生成的类型出行经纬度排序报错
[type=illegal_argument_exception,
reason=failed to find mapper for [location] for geo
distance based sort]]
查询索引字段类型发现location字段不是"geo_point"类型
get http://192.168.43.100:30105/car/_mapping
解决思路:
因为7.x不能修改字段类型 我们需要创建一个临时索引将原来的数据拷贝过来
创建临时索引
put http://192.168.43.101:30105/car_temp
{ "mappings": {
"properties": {
"addressName": {
"type": "text"
},
"adress": {
"type": "text"
},
"beginDate": {
"type": "text"
},
"brand": {
"type": "text"
},
"location": {//修改过后的类型
"type": "geo_point"
},
"name": {
"type": "text"
},
"price": {
"type": "float"
},
"type": {
"type": "text"
}
}
}
}
}
将原来的索引数据拷贝到临时索引
POST http://192.168.43.101:30105/_reindex?refresh&wait_for_completion=false
{
"conflicts": "proceed",
"source": {
"index": "car"//原来索引
},
"dest": {
"index": "car_temp",//临时索引
"op_type": "create"
}
}
错误处理
新增带有经纬度字段时序列化报错 reason=field must be either [lat], [lon] or [geohash]
解决方式需要在GeoPoint类型进行jaskson序列化
package proxy.service.elasticsearch.config;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import org.elasticsearch.common.geo.GeoPoint;
import java.io.IOException;
public class GeoPointDeserializer extends StdDeserializer<GeoPoint> {
private static final long serialVersionUID = -5510642578760781580L;
public GeoPointDeserializer() {
this(null);
}
GeoPointDeserializer(Class<GeoPoint> t) {
super(t);
}
@Override
public GeoPoint deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
ObjectCodec codec = p.getCodec();
JsonNode node = codec.readTree(p);
JsonNode latNode = node.get("lat");
double lat = latNode.asDouble();
JsonNode lonNode = node.get("lon");
double lon = lonNode.asDouble();
return new GeoPoint(lat, lon);
}
}
package proxy.service.elasticsearch.config;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import org.elasticsearch.common.geo.GeoPoint;
import java.io.IOException;
public class GeoPointSerializer extends StdSerializer<GeoPoint> {
private static final long serialVersionUID = -1262685290185555664L;
public GeoPointSerializer() {
this(null);
}
GeoPointSerializer(Class<GeoPoint> t) {
super(t);
}
@Override
public void serialize(GeoPoint value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeStartObject();
gen.writeNumberField("lat", value.getLat());
gen.writeNumberField("lon", value.getLon());
gen.writeEndObject();
}
}
#将序列化对象添加到ObjectMapper
package proxy.service.utils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.elasticsearch.common.geo.GeoPoint;
import proxy.service.elasticsearch.config.GeoPointDeserializer;
import proxy.service.elasticsearch.config.GeoPointSerializer;
public class JSONUtils {
private static ObjectMapper objectMapper;
private ObjectMapper getCurrentObjectMapper(){
return objectMapper;
}
private JSONUtils(){
objectMapper = new ObjectMapper();
}
private static class child{
private static final JSONUtils jsonUtils = new JSONUtils();
}
public static ObjectMapper getObjectMapper(){
ObjectMapper mapper = child.jsonUtils.getCurrentObjectMapper();
SimpleModule deserializerModule = new SimpleModule("GeoPointDeserializer", new Version(1, 0, 0, null, null, null));
deserializerModule.addDeserializer(GeoPoint.class, new GeoPointDeserializer());
mapper.registerModule(deserializerModule);
SimpleModule serializerModule = new SimpleModule("GeoPointSerializer", new Version(1, 0, 0, null, null, null));
serializerModule.addSerializer(GeoPoint.class, new GeoPointSerializer());
mapper.registerModule(serializerModule);
return mapper;
}
public static String toBeanString(Object object){
String res = null;
try {
res = getObjectMapper().writeValueAsString(object);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return res;
}
}
ElasticSearch对位置进行查询和排序
{
"query":{
"bool":{
"must":[
{
"match_all":{}
}
],
//给出一个中心点,查询距离该中心点指定范围内的文档:
"filter":[
{
"geo_distance":{
"distance":"600km",
"address":{
"lat":34.288991865037524,
"lon":108.9404296875
}
}
}
]
}
},
//给出一个中心点,排序:
"sort":{
"_geo_distance":{
"address":{
"lat":34.288991865037524,
"lon":108.9404296875
},
"unit":"km",
"order":"asc"
}
}
}