本文来自获得《2021MongoDB技术实践与应用案例征集活动》一等奖作品
摘要
MongoDB在2.4版中引入全文索引后几经迭代更新已经比较完美地支持以空格分隔的西语,但一直不支持中日韩等语言,社区版用户不得不通过挂接ElasticSearch等支持中文全文搜索的数据库来实现业务需求,由此引入了许多业务限制、安全问题、性能问题和技术复杂性。作者独辟蹊径,基于纯MongoDB社区版(v4.x和v5.0)实现中文全文搜索,在接近四千万个记录的商品表搜索商品名,检索时间在200ms以内,并使用Change Streams技术同步数据变化,满足了业务需要和用户体验需求。
本文首先描述遇到的业务需求和困难,介绍了MongoDB和Atlas Search对全文搜索的支持现状,然后从全文搜索原理讲起,结合MongoDB全文搜索实现,挂接中文分词程序,达到纯MongoDB社区版实现中文全文搜索的目标;针对性能需求,从分词、组合文本索引、用户体验、实时性等多方面给出了优化实践,使整个方案达到商业级的实用性。
业务需求和困难
电商易是作者公司的电商大数据工具品牌,旗下多个产品都有搜索商品的业务需求。早期的时候,我们的搜索是直接用$regex去匹配的,在数据量比较大的时候,需要耗时十几秒甚至几分钟,所以用户总是反馈说搜不出东西来。其实不是搜不出来,而是搜的时间太长,服务器掐断连接了。加上我们普遍使用极简风格的首页,像搜索引擎那样,有个框,右侧是一个“一键分析”的按钮,用户点击后显示相关的商品的数据。搜索成为用户最常用的功能,搜索性能的问题也就变得更加突出了,优化搜索成为了迫在眉睫的任务。
MongoDB在2.4版中引入文本索引(Text Index)实现了全文搜索(Full Text Search,下文简称FTS),虽然后来在2.6和3.2版本中两经改版优化,但一直不支持中日韩等语言。MongoDB官网推出服务Atlas Search,也是通过外挂Lucene的方式支持的,这个服务需要付费,而且未在中国大陆地区运营,与我们无缘,所以还是要寻找自己的解决之道。
那么能否仅仅基于MongoDB社区版实现中文全文搜索呢?带着这个问题,作者深入到MongoDB文本索引的文档、代码中去,发现了些许端倪,并逐步实现和优化了纯MongoDB实现中文全文搜索的方案,下文将从全文搜索的原理讲起,详细描述这个方案。
过程
全文搜索原理
倒排索引是搜索引警的基础。倒排是与正排相对的,假设有一个 ID 为 1 的文档&