背景
在开发一个新的需求的过程中,涉及到有些查询量大,频次高,搜索条件复杂,所以会将数据存到elasticsearch中,一方面可以提高性能,另外减小数据库的压力。
业务逻辑
在创建一个业务单据的时候,会同时在数据库和es集群中插入数据,数据接口基本一致,业务操作不外乎增删改查,索引按月分,工程-表-yyyyMM的方式命名,索引新增记录的时候自动创建。
踩坑过程
- 代码写完了就进行单元测试,首先创建数据,一条OK,检查数据库、es都没问题;然后一次创建多条。继续检查数据库、es没问题,心里感觉稳了一半。
- 然后执行搜索逻辑,一开始es索引计算出了点小问题,不大,很快弄好;首先不带条件查询一次,每页10条,结果ok,正常,感觉自己的代码写的很稳,心情愉快。
- 一切的噩梦从此开始,查询条件有个时间范围搜索,这种情况,肯定挑最复杂的测试了,赶紧设置一个本月第一天到最后一天最后一秒的范围,这绝对能覆盖到数据了。运行之后,诶,怎么查不到数据,一定是我姿势不对,再来亿遍,还是不行!!!。
- 赶紧看下es查询语句是啥,断点到下面的语句,
SearchResponse searchResponse = requestBuilder.get();
- 然后debug模式下的值计算看一下requestBuilder.toString()是什么情况,es查询语句如下,目测毫无问题,
{
"from" : 0,
"size" : 10,
"post_filter" : {
"range" : {
"createTime" : {
"from" : "2020-03-01 00:00:00",
"to" : "2020-03-30 23:59:59",
"include_lower" : true,
"include_upper" : true
}
}
},
"sort" : [ {
"createTime" : {
"order" : "desc"
}
} ]
}
- 将语句放到elasticsearch-head中查看一下,竟然真的查不到数据。这个时候感觉不是代码问题了,是es的哪里配置的问题。
- 首先去看下其他地方使用es的方式,发现java代码大同小异,都是使用api进行调用,先排除一下代码问题。
- 考虑到加上搜索条件有问题,去掉搜索条件就没问题,考虑是不是这个字段的问题,然后查询了一下其他的精确查找的字段(比如:id),发现也没问题。
- 然后删掉这个索引,将date类型使用timstamp 时间戳的方式存储,然后搜索条件中就不是时间格式而是数字了, 再次查询,查询条件也处理成long数字,搜索条件正常生效,现在看来是date类型字符串没法查,但是不能就这样改成long类型保存,不利于查看数据。
- 查了下文档,突然想起来es会存在分词搜索的问题,所以赶紧确认下字段的分词效果,elasticsearch-head可以直接查看索引详情,方便,果然 createTime 只有type是string,默认是会分词的,
"mappings": {
"test-type": {
"properties": {
"createTime": {
"type": "string"
}
}
- 至此找到了问题点,赶紧去创建一波mapping,把所有的字段一个个type,index全部配置好, 然后通过api创建mapping,结果竟然失败了,提示: orderType int 不能转为string, 赶紧检查了一下mappings,发现也确实没写错
- 猜想是不是已经有这个index的问题无法创建了,所以先删除index再创建一次,还是报类似的错误。
- 接下来elasticsearch-head上查看索引信息,发现总是会存在了一个其他的mappings,名字为product,然后有部分字段与我现在要增加的订单中字段相同,但是全部用的string,这个时候基本猜到是因为同一索引,不同type字段类型必须相同导致的。
- 重新创建一个新的索引,把名字加长一点,原来是比如: project-biz-202003 现在改成 project-biz-abc-202003,这样就是不同索引了,再次创建mappings,卧槽,竟然还报错,然后新增一条数据看下,再去检查索引详情,真是怪了,product又出现了,阴魂不散啊。
- 到此我已经花了3个小时了,我都快怀疑自己了,上个厕所路上就想是不是在哪里配置了一个规则会自动创建product这个mapping,然后就去公司的在线文档去搜索,搜了很多页,终于发现一个地址:[http://ip:9200/_plugin/kopf/#!/cluster],这比elasticsearch-head好用多了,然后一路找里面的功能,找到了这个:
image.png
- 终于发现问题了,原来很早以前有人创建了一个project-biz-*的索引模板,只要是符合在规则的索引都会创建一个该模板配置的mappings。
- 找到原因就好弄了,重新将新的业务es所以命名为与之不匹配的名字,比如project-business-table-*,将mappings配置加进去,完成。
- 测试一下,新增-查询-带参查询-范围查询全部ok了,至此坑踩完了。
结论
- 首先使用es前基本的操作要熟悉,比如查询语句怎么写,会查文档。
- 存储新的数据到es,要提前创建mappings,设置好每个字段分词策略
- 创建index template的时候 template的命名最好不要太大的匹配,如果有人以公司名开头的xx-* ,那后来的人就很麻烦了,所有的索引都会匹配上这个规则,所以 最好是 [工程名-业务-表-*]的方式,这样每个template就不会被有冲突了。
image.png
- 这次的坑其实不应该踩的,问了几个同事竟然都不知道有这个mappings,说明公司在这方面没没有好好的沉淀,文档上面都只有一个后台地址,并没有告诉具体要做什么,所以我新加了一个文档说明,给后来的同事参考。
网友评论