大概说一下前段时间用elasticsearch遇到的几个坑

es版本为7.7.1

原始需求

千万级会员,三个条件模糊搜索(左匹配),使用mysql大概要30多秒,因为体验太差所以考虑用es做优化。

实际上,这种需求并不是es主要针对的场景,但是用也可以用,效果也不错,同样的搜索条件0-3s。因为最终结果会比mysql少一些数据,所以在准确率95-99%之间,在我们可以接受的范围之内。

遇到坑和问题

文档不准确

es版本更新快,官网的入门教程还是基于es2.0写的,用的时候遇到许多语法不支持,所以只能去看对应版本英文文档。包括网上的一些教程、博文的版本都各不相同。

解决方案:

没有办法。。。更新太快导致官放教程都没维护,入门的话就只能对比着对应版本的英文文档看了,只能多踩一些坑。

索引的映射类型type失效

官方解释:

在Elasticsearch6.0.0或者或者更新版本中创建的索引只会包含一个映射类型(mappingtype). 在5.x中创建的具有多个映射类型的索引在Elasticsearch6.x中依然会正常工作。在Elasticsearch7.0.0中,映射类型将会被完全移除。

解决方案:

创建索引不指定type,使用默认的就行,这个字段现在已经没有任何作用。

索引的字段的string类型

在ElasticSearch 5.x 之后,字符串类型有了重大改动,移除了String类型,而拆分成了两个新类型keywordtext

text类型:

  • 会进行分词,分词后建立索引。【比如:对于‘佟永硕’,ik分词器的smart分词会自动将其分成佟、永、硕三个字符进行建立索引,所以单字符搜索可以搜索到,而比如‘永硕’则搜索不到】

  • 支持模糊查询,支持准确查询。

  • 不支持聚合查询

keyword类型:

  • 不分词,直接建立索引。【依据此特点,可以使用keyword类型+wildcardQuery(通配查询)实现类似sql的like查询(模糊搜索)】
  • 支持模糊查询,支持准确查询。
  • 支持聚合查询。

如果你是跟着教程使用string的字段类型创建的索引,他会自动变为text,而根据我的需求,我需要的其实是keyword类型的字段,所以前几次数据总是很奇怪,因为被分词了。

分页

elasticsearch在分页上面可以说是极其不擅长了。。。

es的分页有两种方案:

  • 搜索时指定fromsize属性。假设每页十条数据我需要第十页的数据,即91-100。我会先查出前100条数据,把91-100条切出来,返回。
  • scroll滚动的方式,有点像游标,第一次查询后,返回一个scroll_id,你用id去进行下一次查询,每次返回固定长度的数据。适合用于下来刷新这种连续翻页的场景。

这两个方案我都无法接受,事实上我使用scroll的方式,手动写了一个分页函数,比如要取100页的数据,就递归滚动100次,试了一下巨慢无比,没有意义。。。

解决方案:

改需求。。。没有错,事实上模糊搜索没有人在乎最后一页的数据,比如说百度谷歌,一般人前十页都不会翻完。于是乎,我们使用from size的方式,永远只返回前1000数据用于分页。

其它

数据初始化: 我直接分片查的mysql格式化后使用bulk这个api直接导入es。一片1w数据,1200多万2个小时左右。事实上有更好的方案。

数据更新:我们有定时器服务,每一段时间拿到有更新的会员数据,覆盖插入进redis,因为我们es数据的id用的是会员卡号,保证唯一。

eskibana的部署: 开发环境的用dokcer就好了,这个琢磨一下应该不复杂。。