Sphinx查询时最关注的是match里面的几个关键字的查询方式,因此每个检索语句下发到每个索引文件中去的时候首先做的就是对关键字进行结构化构建,得到的第一棵树是n叉树,然后这颗n叉树会进行第二次重构,重构以后的就是一颗有序的二叉树,每个二叉树非叶子节点就是需要做的操作,而每个叶子结点都代表了一个关键字。
上图为sphParseExtendedQuery函数构建的一颗n叉树,代表了match(‘affrow_199 & (affrow_0 | affrow_99 | (affrow_1 & affrow_2)) & pokeman & cpt_20170615 ’)这样的一个查询关键字序列。此时的这棵树还不能进入真正的检索,sphinx会在创建ranker时通过sphCreateRanker函数很隐晦的调用ExtRanker_None_c初始化->ExtRanker_c初始化->ExtNode_i::Create,通过create函数创建一颗可操作的二叉树。
上图就是转化后的二叉树,所有的ExtAnd与操作都排序过了,其中无命中的pokeman关键字在最前。这是通过dTerms.Sort ( ExtNodeTF_fn() )完成的对命中数进行升序排序,也就是保证最小的关键字先进行与操作。
与操作
从spd文件中得到了具体的数据块以后,由于三元组排序可以得知每个关键字的DocId序列是各自有序的,因此每个二叉树的两个DocId序列只需要进行简单的match排序就行了,pCur0和pCur1进行对比,哪个小就自行向后走一位,直到两者相同,则压入结果集然后同时向后走一位,时间复杂度O(m+n)。
或操作
和与操作类似,或操作也是match排序,如果不同则压入小的pCur然后该pCur向后走一位,如果相同则压入一个pCur然后两个都向后走一位。
与非操作
与非则是以第一个pCur为基准和第二个pCur进行match,如果有一样的则跳过一样的