本文已参与「新人创作礼」活动,一起开启掘金创作之路。
近期在工作中需要使用es进行简单的全文检索,所以最近都在边学边做笔记,也会把自己遇到的bug以及如何解决的,一并记录在这里,供大家学习参考。
问题描述
索引结构定义:
{
"test_xxx" : {
"aliases" : { },
"mappings" : {
"properties" : {
...,
"xxx1Doc" : {
"type" : "nested",
"properties" : {
"xxxName" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"xxxValue" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
},
"analyzer" : "ik_max_word",
"search_analyzer" : "ik_smart"
}
}
},
...,
"xxx2Doc" : {
"type" : "nested",
"properties" : {
"xxxName" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"xxxValue" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
},
"analyzer" : "ik_max_word",
"search_analyzer" : "ik_smart"
}
}
}
}
}
}
}
在项目中有对应多个xxxDoc这种类型的字段,通过kibana使用put语句进行赋值,语句如下:
PUT test_xx/_doc/1
{
...,
"xxx1Doc": [{
"xxxName": "xxx",
"xxxValue": "xxx"
},{
"xxxName": "xxx",
"xxxValue": "xxx"
}],
"xxx2Doc": {}
}
代码中的实体类定义如下:
@Document(indexName = "test_xxx")
public class Entity implements Serializable {
@Id
private String Id;
...
private List<XXXEntity> xxx1Doc;
private List<XXXEntity> xxx2Doc;
private List<XXXEntity> xxx2Doc;
private List<XXXEntity> xxx2Doc;
private List<XXXEntity> xxx2Doc;
...
service层:
query.withQuery(boolQueryBuilder);
SearchHits<Entity> result = elasticsearchRestTemplate.search(query.build(), Entity.class);
报错内容:
org.springframework.data.mapping.model.MappingInstantiationException: Failed to instantiate java.util.List using constructor NO_CONSTRUCTOR with arguments\
at org.springframework.data.mapping.model.ReflectionEntityInstantiator.createInstance(ReflectionEntityInstantiator.java:65) ~[spring-data-commons-2.3.9.RELEASE.jar:2.3.9.RELEASE]\
at org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator.createInstance(ClassGeneratingEntityInstantiator.java:87) ~[spring-data-commons-2.3.9.RELEASE.jar:2.3.9.RELEASE]\
at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter$Reader.readEntity(MappingElasticsearchConverter.java:325) ~[spring-data-elasticsearch-4.3.4.jar:4.3.4]\
at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter$Reader.read(MappingElasticsearchConverter.java:262) ~[spring-data-elasticsearch-4.3.4.jar:4.3.4]\
at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter$Reader.readValue(MappingElasticsearchConverter.java:463) ~[spring-data-elasticsearch-4.3.4.jar:4.3.4]\
at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter$Reader.readValue(MappingElasticsearchConverter.java:447) ~[spring-data-elasticsearch-4.3.4.jar:4.3.4]\
at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter$Reader$ElasticsearchPropertyValueProvider.getPropertyValue(MappingElasticsearchConverter.java:634) ~[spring-data-elasticsearch-4.3.4.jar:4.3.4]\
at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter$Reader.readProperties(MappingElasticsearchConverter.java:409) ~[spring-data-elasticsearch-4.3.4.jar:4.3.4]\
at org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter$Reader.readEntity(MappingElasticsearchConverter.java:332) ~[spring-data-elasticsearch-4.3.4.jar:4.3.4]\
...
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [java.util.List]: Specified class is an interface\
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:136) ~[spring-beans-5.2.15.RELEASE.jar:5.2.15.RELEASE]\
at org.springframework.data.mapping.model.ReflectionEntityInstantiator.createInstance(ReflectionEntityInstantiator.java:62) ~[spring-data-commons-2.3.9.RELEASE.jar:2.3.9.RELEASE]\
... 77 more
问题分析
单目调试拿到搜索语句,在kibana中进行测试,正常返回结果,那说明搜索语句没有问题。
看报错提示貌似是因为我定义的实体类和索引中的类型没有匹配,我一度以为是nested类型的数组形式,不能通过list集合这样去定义,花了一天的时间都在搜代码中应该怎么样去定义,尝试过很多方法,都不能解决这个问题。
因为以doc结尾的字段有很多,想着先只留两个试试,结果发现,哎!!!成功返回了竟然。接下来就是一个字段一个字段的去排除问题,后来发现,当我查询所有数据时,有些字段返回结果是这样的:
"xxxDoc" : { },
"xxxDoc" : { },
"xxxDoc" : { },
"xxxDoc" : { },
好像知道问题在哪里了,虽然我在创建索引的时候,有去设置字段的信息,不过put数据的时候,有些字段我是这样放值的:
"xxx2Doc": {}
我往里面放了一个空的数据!!!
解决方案
现在知道问题出在哪里了,搜索语句,实体类的定义都没有问题,就是我的put语句,有些时候我们可能不会往某些字段去存值,在put语句中,就可以直接不写那个字段,而不是像我这样去做。
修改好数据之后,问题就都解决啦!!!😊