关于functionQuery的一个误区

阅读更多

        之前我在跟别人分享solr(lucene)的时候,在谈论到一些特殊的query,比如prefixquery、wildcardQuery的时候,我曾经说过一句话:query就是得到词典表中的term,然后判断是不是符合条件,有的query(比如termquery)仅仅是判断词典表中的词和要查找的词是否相等,prefixQuery是判断是不是以制定的字符串开头,wildcardQuery是判断是不是符合某个正则表达式,等等,我们可以实现更加复杂的query来实现更加复杂的条件,比如function query。当然这句话纯粹是我自己的判断,没有实际的例子证明。

       今天我在读了function query的代码后,发现我想错了,funcitonQuery并不是为了实现复杂的判断逻辑而存在的。我先说一下他都是做了什么吧,他里面有一个vlaueSource(就是获得索引中的某些值,可能是来自于doc的某个属性,也可能是需要现计算出来的一些值,在下面会有介绍),然后他在计算得分的时候使用了这个valueSouce中对于某个id的doc的值,是作为一个数字加到默认的得分上去的,默认的得分只有一个参数,那就是使用的query的boost,他的结果是返回所有的doc,看看FunctionQuery生成的FunctionWeight的scorer方法,

 @Override
public Scorer scorer(AtomicReaderContext context, Bits acceptDocs) throws IOException {
      return new AllScorer(context, acceptDocs, this, queryWeight);
}

他是返回了一个AllScorer,顾名思义也知道他是返回所有的doc的scorer,看看他的next方法吧:

 @Override
public int nextDoc() throws IOException {
  for(;;) {
    ++doc;
    if (doc>=maxDoc) {
      return doc=NO_MORE_DOCS;
    }
    if (acceptDocs != null && !acceptDocs.get(doc)) continue;
    return doc;
  }
}

  可以看出,只要一个doc没有被删除就会被返回,所以可以确定的说这个AllScorer就是返回所有的doc。

我用solr做了一个例子,使用function query,发现他获得了所有doc,例子为:使用edismax的queryParser,q设置为:{!func}sub(someField,22),在debugQuery的情况下,我看到了他的确是生成了一个FunctionQuery。

 

  上面我说的复杂的倒排表的选择是这个意思:比如我要在一个人才的lucene的索引中查找身高和体重符合一定条件的人(比如加起来是300的,如果一个人身高170,130斤,那么就应该召回),本来我以为function query就是要实现这种复杂逻辑的呢,但是在我看了他的源码之后,发现他不是做这个的。因为他仅仅是突出的使用了valueSource,valueSource是来自于field cache(也就是词典表或者docValue),而这个显然无法和倒排表扯上关系,所以我可以肯定的说,function query的作用很简单,就是利用valueSource来计算一个简单的得分的。

  那么既然FunctionQuery的作用那么小,那用它来做啥子呢?

 

  很简单,作为排序的一个条件,因为他只能计算valueSource的值和自己的boost,那就可以很方便的使用它计算一个值作为排序的标准,在solr里面使用它就是一个很好的例子!

 

  既然用到了value source,就说一句吧,value source就是获得一个doc的某个值,比如可以是一个域的值,或者是多个域的值得函数值(比如域中某些term的tf),也可以是指定的某个常数的值(比如常数类型的valueSource),这就能很好的理解solr中的那些函数了,比如max、sub、div,这些就是对一个doc的多个域的值进行一个函数操作后把最后的结果用来计算得分的。所以这样一来,理解solr的那些函数就很简单了,我们也就能自己实现一些函数来实现更加复杂的功能了!

 

  最后再重复一边,functionquery并不是一个复杂的query,我之前理解错了,纠正这个误区!

 

 

你可能感兴趣的:(function,query,value,source)