问答
温馨提示
在框架使用中,难免会因为各种原因导致异常,我们不排除框架本身有缺陷(通常小于0.1%)导致,但目前发布的功能中,都是稳定且有测试用例覆盖及大量用户生产环境验证过的,更多的时候是依赖不兼容或用户没有按文档使用,自由发挥,导致出现一些问题,这类用户通常还比较懒,一碰到鸡毛大点问题马上来群里问,或是抱怨框架垃圾,然后我们协助排查解决最后发现是xx地方没有按文档使用,而是胡乱搞,我们也很无奈,毕竟做开源,精力和时间也比较有限,我们想把时间花在刀刃上,比如收集真正的bug,去迭代解决,而不是把时间浪费在这些无谓的地方. 所以我们还是希望用户能在使用前多读文档,遇到问题不妨先从文档下手,看看我们提供的高频问答中是否有您想问的问题,看看我们提供的DEMO是怎么写的?DEMO中实际依赖的es,fastjson,springboot版本是多少,不妨先把你项目中的依赖版本与demo中保持一致,排除依赖原因. 如仍未解决可以打断点找找原因,看看源码分析分析,经历了这些步骤,如果仍然解决不了,可以再来答疑群里问,这是一个码农基本的素养,而且对提升自身技术水平有很大帮助,如果碰到问题就抛出去,久而久之,自我独立解决和分析问题的能力会越来越差,长此以往,若有一天用了某款开源产品,碰到问题恰好没人答疑,又当何去何从?
当碰到有一些需求EE提供的API不支持时怎么办?
没关系,作者早就帮主公们想到最优的解决方案了,请查看这里:混合查询
使用过程中,报错:java.lang.reflect.UndeclaredThrowableException
Caused by: [daily_document] ElasticsearchStatusException[Elasticsearch exception [type=index_not_found_exception, reason=no such index [daily_document]]]
如果您的错误信息和原因与上面一致,请检查索引名称是否正确配置,检查全局配置,注解配置,如果配置无误,可能是索引不存在,您可以通过es-head可视化工具查看是否已存在指定索引,若无此索引,可以通过EE提供的API快速创建.
使用wrapper.eq(xx::getXX,"查询内容")查不出来数据?
eq对应的是es的TermQuery(),需要被查询字段的索引类型为keyword时才能查询,如果被查询字段的索引类型为text,那么该字段将无法被eq查询,在使用前不妨先看看自己的需求,是否需要分词匹配,如果需要分词匹配,把该字段的索引类型建立为text类型,然后使用wrapper.match(),wrapper.queryString()等方式查询;如果需要精确匹配,可将该索引字段类型建立为keyword类型,然后使用wrapper.eq()查询; 如果同一个字段,既需要用精确匹配查询,又需要被分词查询,可将其索引类型创建为keyword&text类型,在把它当作keyword类型查询时,需要传入字段名称为“字段名称.keyword”,在把它当text类型查询时,直接用字段名即可。或者不妨将该字段冗余,新增一个字段,值与该字段保持一致,一个索引用keyword,一个用text类型,这样就可以完美化解了,对es而言支持PB级数据,增加一个冗余字段,对性能影响微乎其微.
process index exception,java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
es单机版的配置的问题所致,并非框架原因.
查询时数据能正常返回,但报noSuchMethod错误?
说明你当前查询的mapper对应实体类中缺少id字段,需要加上
public class xxxEntity{
// 省略其它字段...
private String id;
}
2
3
4
新增数据时报错
java.lang.reflect.UndeclaredThrowableException: null
99%的情况是你的实体类中使用了嵌套对象,但实际该对象上的注解却指定为@IndexField(fieldType=Object)所致.
嵌套对象必须使用嵌套对象的语法,参考文档嵌套类型,剩余1%情况是你项目中实际引入的fastjson依赖版本过低/过高所导致,建议与我官方提供的demo中保持一致或与框架底层依赖的fastjson版本保持一致.
调用insert或insertBatch接口时,报错 the entity id must not be null
检查配置文件中全局id策略id-type是否为customize,以及@IndexId注解中的idType值是否为IdType.CUSTOMIZE,如果为此值则代表id由用户自定义传入,所以在插入数据前需要用户主动为该数据的id设置值,然后再插入.
项目启动时报错 java.lang.NoClassDefFoundError...AliasMetadata
具体报错内容 process index exception,java.util.concurrent.CompletionException: java.lang.BootstrapMethodError: java.lang.NoClassDefFoundError: org/elasticsearch/cluster/metadata/AliasMetadata
出现此报错信息,则说明ES相关依赖冲突,解决方案其实很简单,可以像下面一样配置maven的exclude移除Springboot或Easy-Es已经声明的ES及RestHighLevelClient依赖,然后重新引入,引入时指定版本号为7.14.0即可解决.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
</exclusion>
<exclusion>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.14.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.14.0</version>
</dependency>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
如果你是个菜的抠脚的懒汉,也可以简单粗暴的把springboot版本调整到2.5.5,其它都不需要调整,也可以勉强正常使用.
索引中出现的索引名带_s0或_s1后缀
无需担心,这是全自动平滑迁移零停机的必经之路,索引后缀不影响使用,框架会自动激活该新索引.关于_s0和_s1后缀,在此模式下无法避免,因为要保留原索引数据迁移,又不能同时存在两个同名索引.
其完整原理可以参考索引托管模式章节.
索引会被追加别名ee_default_alias
无需担心,每个索引都可以有N个索引别名,此别名主要用于方便框架底层对框架自动托管的索引进行管理,相当于给索引打了个标签,是追加机制,不会影响你已有索引别名,就好比你真名叫老汉,别人给你取了个外号叫猛男,叫帅哥,叫糟老头子坏得很...并不影响你的真实身份是老汉.
支持跨索引CRUD吗?
针对索引结构相同的情况,用户可在wrapper.index(indexName1,indexName2...)指定当前操作生效的索引,若方法无wrapper,可以直接在对应接口中传入,比如insert(entity,indexName1,indexName2...),要求索引结构必须相同才可以,否则无法执行成功,
此功能适用于索引结构是按日期生成的用户,比如按月,按年生成,只是索引名称不同,但索引结构相同,就可以通过此方案来解决CRUD中的困惑.
为什么通过@IndexField注解指定的索引类型为keyword(或其它类型),实际创建出来的索引类型却是下图这样,这是为啥?
- 首先你需要确认当前索引开启的是"自动挡模式",默认是开启的,如果是手动挡模式,自定义注解指定的索引类型,仅在下面这两个api中生效,对于纯自定义的场景并不会生效.
Boolean createIndex();
Boolean createIndex(String indexName);
2
因为纯自定义的场景为了保证原生的灵活性,索引的类型等所有信息均由用户自己指定,而非自定义注解.
- 其次你需要确认在自动挡模式或上述两个API进行创建索引时,是否创建成功,索引创建成功的标志是项目启动时控制台打印出 ===> Congratulations auto process index by Easy-Es is done !
如果控制台打印出===> Unfortunately, auto process index by Easy-Es failed...则说明索引托管失败了,具体原因可以看看紧随其后的日志. 不过经过这么久的社区答疑,99.99%的情况都是下面这两种原因,可供参考:
- 底层es或RestHighLevelClient依赖版本冲突了,由于EE底层用的es和RestHighLevelClient依赖版本是7.14.0,ES本身版本兼容做的又比较差,而Springboot有springdata-es,所以它内置了和es的对应版本,因此不可避免的会出现因为springboot版本不同带来的es依赖冲突,导致很多功能不兼容,进而导致索引托管失败,可以将es和RestHighLevelClient版本统一为7.14.0,不会的话请自行百度依赖冲突如何解决,这是java程序员的基本技能了,如果你还不会赶紧去学,我真的栓Q,不要再问我这种低级问题!
- 实体类中使用了嵌套类型,但未按照嵌套类型的使用文档去配置,导致索引托管失败了,很多人不知道嵌套类型是啥,简单来说就是你实体类中引入了其它自定义的对象或者Map.
- 实体类中使用了List<String|Integer等包装类型...>,此时该字段的索引类型应该定义为text而非array, 查询时可以通过wrapper.match查询,es默认分词器会通过数组中的逗号把具体数据给查出来.
那么有用户纳闷了,为啥你都说索引托管失败了,可实际上索引却是存在的,通过es-head也能看到,并且该字段的类型是keyword&text类型,这是因为在该字段不存在的情况下,如果你调用了数据插入/更新api,es本身(非easy-es)也会帮你自动创建索引,创建的索引字段类型默认就是keyword&text类型
为什么通过eq查不出来数据? 通过match查不出来数据 通过xxx查不出来数据? 首先你要明确eq对应的是es的termQuery,match对应的是matchQuery...具体可参考MySQLy和EE语法对比 term查询要求字段类型为keyword,matchQuery则要求字段类型为text,并且如果是中文的话需要安装中文分词器,比如ik,然后在索引中正确创建和配置,才能查询出来. 查不出来不妨先检查你的索引类型,分词器,以及分词器是否能把你输入的关键词给分出来,原文中是否能命中,存储和查询是否用的同一种分词器等都需要先确认,而不是上来就质疑框架有bug,框架已上线的功能都是有单测覆盖并且大量用户使用的,否则也不会轻易上线.