一、 多条件的查询方法:
之前已经介绍过倒排索引的结构。在查单个词的时候比较简单,直接查从索引里找是否有这个词对应的文档列表就行了。但如果条件是and、or、not这样的条件,怎么处理呢?
and:对多个条件分别取文档列表后,再取交集。
or:对多个条件分别取文档列表后,再取并集。
not:对多个条件分别取文档列表后,再取补集。
曾经以为这样效率不高,但仔细想想。索引列表压缩后最多也就几mb的数据,这已经可存百万级的列表了,在内存中对几个几mb的数据遍历一下也要不了多少时间,更不用说可用二分等更高级的算法了,效率不是问题。
二、如何按相关性排序?
比如用户搜"秋季
瘦身",可先按上面or的处理方法取出并集,但这么多的文档怎么按相关性排序呢?如果索引里的值已经足够计算相关性,那么直接用索引里的值,不够再读取相应的文档。具体方法有一次一单词(Term
at a Time)、一次一文档(Doc at aTime)、跳跃指针(Skip Pointers)。
三、多字段的索引怎么存储
1.每个字段做一个索引文件,如下
标题字段
描述字段
2.在字段信息存在索引里:
这个字段可以不用名称,可每个字段用一个比特位来表示。如总共有2个字段,则上对于"美容"这个词的值为Doc7(tf,idf)(11),doc8(tf,idf)(10),Doc6(tf,idf)(01)
3.扩展列表方式
对每个字段做一个扩展列表,如下:
标题字段扩展 {doc1,(1,4)},{doc2,(6,8)}
{doc1,(1,4)}的意思是文档1的标题所占的位置是1到4,其它类推。
那么倒排列表结构可这么存:
美容: [doc1,(6,8)], [doc2,(7)]
那么"美容"这个词在文档1的位置是6到8,并没有在上面的1到4里,就是说标题里没有"美容"这个词。同理"美容"这个词在文档2的标题里。
四、检索效果评价
1.精确率Pr
Pr=检索结果中与检索相关的结果数 / 全部检索结果数
如,在检索某个查询的答案时,取前50个文档。而且这35个文档是与查询相关的,则精确率为P50=70%
。为什么是这么计算,其实是有前提的:就是相关的才被查出来。这与我们的实际工作有些区别,有时我们要尽可能给用户提供更多的选择,相关也是有相关度的区别的。如果返回的前35个就是最相关的,而且除了这已经没有最相关的了,其它的是15个是次相关的,这个精确率就应该是100%
。
2.召回率Rr
Rr=与检索相关且实际检索出的文档数 / 与检索相关的文档数
还是前面那个例子,实际检索出的前50个文档中有35个是相关的,但是真正相关的有70篇,那么召回率R50=50%,因为在前50篇文档中只选出了35/70=50的相关文档。
一般在用ik这样的中文分词,如果单从词的匹配的角度来看,精确率应该都是100%。但如果从一个用户的观点看,可能在第10页的数据才是他认为是精准匹配的,所以这样的问题得具体问题具体分析,使用不同的算法来解决。