沙师弟,师父的充电器掉了

Lucene里的王安德打分器

Lucene | 作者 Charele | 发布于2024年04月13日 | 阅读数:3780

B2FA9AC34654DD68ACE9161C2C56DF66_w1280h720.jpg

 
WAND即 : Weak AND,
WAND打分器,用在boolean查询的should类型中,
比如我要找"000" or "111" or "222" or  "333" ,,, or "999, 这10个词中,必须最小满其中的8个。
 
https://amazingkoala.com.cn/Lu ... 2589/
这里有介绍,但他只介绍了基本思想,
并没有明细的表述,可能是忘了写第二章了吧
 
 
 
 
 
 
已邀请:

Charele - Cisco4321

赞同来自:

1234.png

Wand的结构和执行过于复杂,能不用尽量不用,
 
PS: bool查询由于选项较多(must等4种条件, 加上minShouldMatch),
所以为了生成布尔查询的打分器,
分叉特别多,而每一个分支会产生一个主题,
所以想对布尔查询有一个清西的理解,可以说非常之困难。
 
现在只谈一下,这棵大树的其中一个分支: Wand打分器 
 
 

Charele - Cisco4321

赞同来自:

1111.png

2222.PNG

同一个类,不同版本的Lucene之间会有差异,
 变化的结果肯定是,新版的越来越复杂:-( 
上面是大神博客里的,他那个版本可能比较老
下面是最新版的

Charele - Cisco4321

赞同来自:

1111.png

文章里有一个可以简化的公式,意思是说,
比如我有10个should条件,必须满足其中的8个,
现在我只要看看10 - 8 + 1 = 3个打分器就可以了。理论上是这样,
但现在版本中,并没有这么做,它还是得满足8个。
 
可能是版本实现不同(理不清的东东,不想去看老版本了),
也可能是我没理解出这个思想体现在哪,有理解的人可以告知一下
 
这个理论只体现在算cost的时候,仅仅用在这儿而已!
2222.PNG

这个代码的意思是,如果10个should子条件,必须满足其中的8个,
(子条件也是查询,也有它自己的打分器)
 我把代码最小的3个子条件的代价相加,
作为这个Wand打分器的代价。
 
这个代价对Wand自身并没有作用,
但如果Wand查询是另外一个查询的子查询(即Wand打分器是子打分器),就有用了

Charele - Cisco4321

赞同来自:

:10个should子条件,必须满足其中的8个(忽略打分)
 
1111.png

 DisiWrapper类用来包装子打分器,
比如你子查询是"TermQuery",那子打分器就是"TermScorer"类型
 
这里面有3个容器变量,
具体的执行过程,就是把10个子打分器在这3个容器里倒来倒去,,,变量1不是容器类型。但DisiWrapper类里有个next变量,指向下一个DisiWrapper对像。形成一个链表

2 数组
3 优先级队列
 

Charele - Cisco4321

赞同来自:

它之所以搞得这么复杂,是有原因的,
1 要算打分, 2 是要考虑子条件(子查询)的代价。
 
设想一下,有3个queue,你要求出所有数字,最少在两个数组中有
A: 0, 1, 4, 5, 10                                代价:10
B: 0, 2, 7, 8, 11, 15                           代价:30
C: 0,  4 5, 6, 11, 100                         代价:20
 
PS: 一个queue,等于Wand打分器中的一个should条件(子打分器),
数字就等于这个子打分器取出来的文档号
 
你很容易就可以看出(程序也很容易实现),0, 4, 5,11满足。
所以,文档0,4,5,11就是满足你这个布尔查询的结果
 
实际中,它会考虑各个子打分器的代价,会先从代价小的子打分器中取文档号。
比如上面,按须序取的话,取完a和b里的0,就知道0是满足了minShould
就不用从c中去取了。
但队列b的代价是最大的,所以它不会从b中去取,会先从a,c中取
 
1111.png

要回复问题请先登录注册