[译]solr boolean operators

踩坑感言:

这个故事告诉我,做事情不要想当然,你觉得的事情,一定不是对的。


译文原文:

来自于Bill Dueber.


结论:

在Solr中一定要用括号去管理优先级!!!


搞起搞起!

用过Solr的同学知道一下查询,Solr是怎么做的么?

a OR b AND C

我可以给你三种选择,但是前两种肯定是错误的,而且你也不会想到第三种,因此还是不要花费太多的时间去想吧。

boolean运算符的优先级

如果你曾经知道过boolean运算相关的知识,你坑定为知道一个严格意义上的顺序,那就是NOT>AND>OR,因此,可能就会使下面一种执行顺序:

a OR (b AND c)

这是猜想答案的一种,但是Solr不是这么做的。

从左到右?

部分本地的学生,或者说也有至少一门编程语言,用的是简单的从左到右的执行方法,因此,就会有如下的一种执行顺序:

(a OR b) AND c

不幸的是,这个还是错的。

那么还有什么答案呢?

正确的执行顺序可以用如下的代码来表示,待会再通过lucene的查询分析来解释下:

(b AND c)

在这里,第一个判断被抛弃了!也就是说,第一个判断其实是可有可无的!

你还会让你的使用者将AND/OR/NOT放在他们的查询里么?

但愿他们并不知道什么是boolean运算;如果他们知道,但愿他们会使用括号,或者你可以帮他们判断出来,不然,他们将会死得很惨。。。。

更多的测试

我在Solr(3.5)的里面测试下所有可以的情况(用的是curly,larry,moe和shemp的排序)总共有15种情况。

我写了个脚本来跑这些情况,分别在lucene和edismax下,看看可以得到什么样的结果。所有的测试中,lucene的默认运算符是AND,edismax的mm参数设置为100%

Lucene                    EDismax

  1. curly AND larry
curly larry               curly larry
curly larry moe           curly larry moe
curly larry shemp         curly larry shemp
curly larry moe shemp     curly larry moe shemp
  1. curly AND larry OR moe
curly                     curly larry
curly larry               curly larry moe
curly moe                 curly larry shemp
curly shemp               curly larry moe shemp
curly larry moe
curly larry shemp
curly moe shemp
curly larry moe shemp
  1. curly OR larry AND moe
larry moe                 larry moe
curly larry moe           curly larry moe
larry moe shemp           larry moe shemp
curly larry moe shemp     curly larry moe shemp
  1. curly AND larry OR moe AND shemp
curly moe shemp           curly larry moe shemp
curly larry moe shemp
  1. moe AND shemp OR curly AND larry
curly larry moe           curly larry moe shemp
curly larry moe shemp

查询1的答案是在预想中的。查询2的答案中,明显的就发现在lucene查询器下只有有’curly’就可以了,而在edismax下就需要’curly AND larry’(查询3一样的是变成了’larry AND moe’)。查询4和查询5也是同样的道理。当然,你可以看下debug查询输出,来知道她们是什么样的运行结果,但是没有告诉我为什么。

启示

好消息就是,不论是lucene还是edismax,在用括号的时候,她们的答案都是显而易见的。
在lucene-167cene的缺陷管理中也确实提到了这个问题(Lucene-167,lucene-1823),而在2005 mailling list thread中也指出也这种现象,但是它还是仍旧存在。

~~~

还是老老实实的用上括号吧,以免再入坑!