写在前面
第一次在简书写博客,一方面是想记录下自己技术学习之路,另一方面将自己的认知提出来与大家沟通交流。
背景介绍
废话不多说,下面分享下在线搜索使用solr的一些调研经验和遇到的坑。
首先说明下,之所以用solr做在线搜索是因为项目组之前有过使用经验,主要是用于日志检索,用的比较简单。但从调研业界的做法来看,Elasticsearch更适合做在线实时搜索,实时搜索的效率是solr的几十倍,到solr也有自己的优势这里不多说,后面补充。
做的产品是新闻客户端。搜索的需求一开始是标题匹配优先,其次文章内容匹配,结果分别按时间倒排。要求模糊匹配,准确度80%(这个匹配度是从产品层面定义,可简单理解为:搜索词是10个字,匹配上8个字才认为匹配上)。
索引
首先做检索肯定需要对需要匹配的字段做索引。在配置文件中设置title和content属性indexed=true,索引的意义不用多说,相当于空间换搜索时间的概念。
分词器
这里介绍下分词器。搜索引擎不可能拿用户输入的词直接去做匹配,所以就需要做分词,目前solr支持的最好的开源分词器是IKAnalyzer(中文分词器)。比如“王宝强和马蓉离婚事件”,理想的分词结果应该是“王宝强”、“和”、“马蓉”、“离婚”、“事件”。如果你认为“和”这个词是无意义影响匹配效果,可在stopword.doc中配置这个词,那么搜索时就会被过滤。(其实IK做不到这样的分词效果,目前应该是哈工大的分词器效果比较理想能做到这样的效果,可用c语言封装so库提供java调用)。
自定义评分
要实现上面的需求最大的难度是需要自定义打分规则,而不是根据匹配度。solr提供了一些函数来改变打分。首先要设置defType为edismax,edismax是boost函数与原score相乘作为打分结果,dismax是相加,一般自定义打分都设置为edismax,因为score是其中一个维度(匹配度)。打分函数是设置bf字段,函数就是 query product exists等solr函数根据自定义规则计算一个打分结果的函数。将计算结果*score,搜索结果按这个最终打分来排。另外还有个参数mm,来控制匹配度,如80%,表示必须分词结果的所有词去匹配,需要80%的词匹配上。
效果分析
按以上策略满足了产品需求,但实际效果比较差,因为自定义评分函数结果对score影响较大,搜索结果前面几条可能匹配度不是最高的,但也满足了80%,有匹配度更高的没有出现在前面。这里就需要对自定义评分函数的参数不断调优,达到一个合理的值。事实上最终我们放弃了这个自定义评分的方案,产品最终一方面是希望按匹配度来排序,另一方面要求匹配的精确度高。最后我们将mm值设为了100%。
结语
在不是必要的前提下,尽量不要使用自定义评分函数,因为会影响打分结果。如果一定要使用,那么需要优化好自定义评分的函数,达到你预期的搜索效果。
这里仅仅是用一个使用实例来抛出了使用solr的话题,一些细节问题待后续持续讨论。