在solr里面,如何合理的控制的命中的数量?
在一些日常的文章中或一些信息中,都有一些高频词,而这些高频词,在参与查询时,往往会造成,大量的结果集命中。
什么意思呢? 举个例子,假如我们现在做的是饭店的搜索,在我们的索引库里有一列name这个field,这里面大部分都是xxx饭店,假如你搜索的时候搜一个xxx饭店,会被分词成:
xxx
饭店
然后xxx命中只有10条结果集, 而饭店确命中了20万结果集,这么以来总结果可能就有20多万条,造成了大量的数据命中,一方面显示了信息的丰富性,另一方面可能给用户造成太多的困惑。
我们分析下在全文检索中两个重要的概念
查准率
召全率
在Lucene,Solr和ElasticSearch里面一般的分词的查询结果都会对这两个率做一个最好效果的调配,而这个默认的相关性评分规则就是:
- 相关性评分最高的排在前面,也就是查准的体现
- 相关性低的排在后面,也就是查全的体现
当然上面的结论,并不是百分百正确的,因为由于Lucene底层的设计,可能会导致一些奇怪的效果,就是最精确的没有排在最前面,这种问题大概只有10%的概率,我们可以索引两个字段,来避免这种问题,一个分词,一个不分词,查询时候,可以一起查询两个字段.
回到刚才饭店的那个问题,假如现在有想要搜索一个:
北京车道沟北里小庄十里香饭店,分词后的情况如下:
车道
沟
北里
小庄
十里
香
饭店
注意,在整个索引库里面大部分要搜索的数据都含有北京和饭店两个词,所以这一下几乎会索引里面的所有数据都查询出来了,虽然查询排名还可以,但命中量太大了,超过4页之后几乎都是北京xxxx饭店了,跟主题的搜索没啥关系,所以我们可以采取一些策略来避免这种情况:
solr默认的搜索策略,是分词后的term的or的关系,最后结果集全部返回,如果我们改成and,那就是精确匹配了,但是有一点就是,如果是精确的匹配,某些时候用户输入的不完整的词就失去了全文检索的含义了,所以我们要采取一种综合的策略,既保证查准,又能保证召回,这样才能实现?
这个东西直接用我们的全文检索框架是没法实现的,有个思路不错,就是我们对要搜索的词,提取出句子的主干,然后主干部分在检索时,是必须要命中的,如果不命中,就算该条数据与查询的词,相关性不大,这个方法不错,但前提是你如何在大规模的数据里面精准的提出这些精确的主干词呢? 使用机器学习或者是文本挖掘? 答案是肯定能做,只是需要另外设计了,这是最好的解决搜索的命中数量太多的办法。
还有一个办法,是一种治标不治本的办法,比较容易实现,就是限制每次分词后最大匹配term的个数,也就是像
车道
沟
北里
小庄
十里
香
饭店
必须命中3个或更多的term,我才认为相关性更大,或者有一个百分比来限制80%以上的命中,就算此条记录不错。这个使用solr的edismax可以解决,方法如下:
使用edismax,在q里写完
name:北京xxxxx饭店后
在Raw Query Paramters参数里面写
defType=edismax&mm=80%25
然后查询即可,mm是最小匹配的数量,可以是个固定的值,也可也是个百分比,因为散仙是在solr的admin页面查询,所以需要把%替换成url字符%25,这样才能正确发送到solr的服务端 具体的资料请看: