`
suichangkele
  • 浏览: 198163 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

lucene3.0.3中的CustomerScoreQuery

阅读更多

      我原本以为我已经把lucene3.0.3看的很详细了,结果发现漏了一个很重要的query——CustomerScoreQuery,从名字上看表示用户自定义得分的query,我表示很好奇,因为我花了好大力气才明白了lucene的得分公式,貌似这里竟然可以自己写得分公式了,于是我抱着极大的好奇心看了他的源码,记录在此,方便大家。

     CustomerScoreQuery的原理是这样的,它包含一个主query以及一个或者多个valueScourceQuery,主query和我们平时的query是一样的,可以是任意的query的子类,valueSourceQuery是用来完成我们自定义得分的,他不会进行召回,召回是主query的功能,对于主query召回的的每一个doc,valueSourceQuery可以对其得分进行修改,修改的规则由CustomerScoreQuery配置的CustomScoreProvider设置,他的主要思想就是这样。ValueSourceQuery对doc的得分的修改是根据其内部的ValueSource属性来设置的,我们从这个ValueSouce下手。

      ValueSource:这个类是个抽象类,他最关键的方法是DocValues getValues(IndexReader reader),他表示从指定的reader中获得的对于每一个doc的值,用DocValues进行封装,DocValues也是一个抽象类,通过调用它的floatVal(int doc)、intVal(int doc)来获得每一个doc的值,这个值就可以影响最终的doc的打分。我们看一个ValueSource的实现类FieldCacheSource,它的逻辑是从词典表中获得每一个doc对应的term,然后根据term进行打分,所以他必须执行一个域(即term所在的域),并且这个域必须建立索引且不能分词(这个和之前的FieldCache的逻辑是一样的)。他对getValues的实现是这样的:

 

/**
 * 获得当前的段下当前的域的值,通过DocValues封装,和Sort是一个逻辑。
 */
@Override
public final DocValues getValues(IndexReader reader) throws IOException {
	return getCachedFieldValues(FieldCache.DEFAULT, field, reader);//这里的field就是我们说的term所在的域的名字。
}

 FieldCacheSource类也是一个抽象类,他的getCachedFieldValues没有实现,我们看一个他的实现类:IntFieldSource.getCachedFieldValues(FieldCache, String, IndexReader),即将每个doc所对应的某个域中的term转换为一个int类型的整数的类,他的逻辑和我们在FieldCache中介绍的是一样,代码如下:

 

@Override
public DocValues getCachedFieldValues(FieldCache cache, String field, IndexReader reader) throws IOException {
	final int[] arr = cache.getInts(reader, field, parser);//将FieldCache中当前的reader下的field域的term用parser转换为int,
	return new DocValues() {
		@Override
		public float floatVal(int doc) {
			return (float) arr[doc];
		}
		@Override
		public int intVal(int doc) {
			return arr[doc];
		}
		@Override
		public String toString(int doc) {
			return description() + '=' + intVal(doc);
		}
		@Override
		Object getInnerArray() {
			return arr;
		}
	};
}

 这样就能获得最终的DocValues了,ValueSource的最终目的就是获得DocValues,然后我们再看一下ValueSourceQuery的过程。

      一个Query最重要的就两个,一个是召回doc(doc的召回是scorer的功能),一个是对召回的doc的打分(打分是weight和scorer的功能),也就是生成weight、scorer的方法,ValueSourceQuery的最终生成的Scorer是ValueSourceScorer,其里面的termDocs是一个AllTermDocs,也就是从所有的域中获得term的termDocs,从这里可以看出valueSourceQuery是如何召回的doc了,只不过他是召回了所有的doc(也就是说他召回的doc实际上是没有用的)。我们再看一下ValueSourceScorer的得分的计算也就是其score方法

 

/* (non-Javadoc) @see org.apache.lucene.search.Scorer#score() */
@Override
public float score() throws IOException {
	return qWeight * vals.floatVal(termDocs.doc());//这里的vals就是从ValueSourceQuery中获得的ValueSource属性
}

 他的得分的计算是通过DocValues来计算的,也就是将缓存的term转换为数字来作为得分,还有个qWeight,他是weight计算出来的值,在默认的情况下他是1,因为他是由ValueSourceQuery的getBoost来计算的(计算出来是1)。这样我们搞懂了ValueSourceQuery最终的功能是召回所有的doc,并将每个doc的term解析为数字作为得分的。接下来我们回到CustomerScoreQuery来看一下他是如何召回doc和计算得分的。

      召回doc和得分都是在CustomerScoreQuery最终生成的Scorer——CustomScorer中计算的,我们看一下召回的方法nextDoc,代码:

 

/** 查找下一个doc时是优先调用subQueryScorer的id,然后让各个valueSource也指向这个doc*/
@Override
public int nextDoc() throws IOException {
   int doc = subQueryScorer.nextDoc();//先根据主query来召回doc,
   if (doc != NO_MORE_DOCS) {//如果召回了
        for (int i = 0; i < valSrcScorers.length; i++) {
   	    valSrcScorers[i].advance(doc);//将每一个ValueSourceQuery的scorer都前进到主query召回的doc,
	}
   }
   return doc;
}

 可以看出召回是根据主query召回的,我们看一下打分:

 

@Override
public float score() throws IOException {
	for (int i = 0; i < valSrcScorers.length; i++) {
		vScores[i] = valSrcScorers[i].score();//计算当前的doc下所有的valueSourceScorer的得分
	}
	return qWeight * provider.customScore(subQueryScorer.docID(), subQueryScorer.score(), vScores);//最终的得分要看provider的实现。
}

 provider通过CustomerScoreQuery的getCustomScoreProvider方法获得,这个类决定了如何计算最终的得分,他的customScore方法:

 

@Deprecated
public float customScore(int doc, float subQueryScore, float valSrcScores[]) {
if (valSrcScores.length == 1) {
	return customScore(doc, subQueryScore, valSrcScores[0]);//如果只要一个valueSourceQuery,是将两个的得分相乘,
}
if (valSrcScores.length == 0) {
	return customScore(doc, subQueryScore, 1);//如果没有valueSourceQuery,则直接返回subQuerScore,乘以1和没乘一样。
}
float score = subQueryScore;
for (int i = 0; i < valSrcScores.length; i++) {//如果有多个,是将所有的得分乘起来。
	score *= valSrcScores[i];
}
return score;
}

 通过上面的分析我们知道了customerScorerQuery的来龙去脉,他就是通过valueSource对通过主Query召回的doc的打分进行修改。那么他的用处是什么呢,我们可以做什么拓展呢?我的理解是我们可以通过对得分进行修改,来影响排序,在CustomerScoreQuery的javadoc中也对此进行了说明:可以通过几成CustomerScoreQuery复写其getCustomScoreProvider方法来实现自己的CustomScoreProvider来实现最终的得分的计算,比如我们在搜电商网站中的商品的时候,对于刚上架的商品要比上架很久的商品排在前面,或者新上架的排在后面,就可以通过自己实现一个CustomScoreProvider,用当前的时间减去doc的上架时间作为一个得分的计算方式,然后再和主query的得分通过一定的方式结合起来做出最后的得分。

 

 

 

      

      

分享到:
评论

相关推荐

    lucene-3.0.3-src.zip

    3. **搜索优化**:Lucene 3.0.3的源码中,可以看到对Boosting、Filtering和Sorting等高级搜索功能的实现,以及对TopDocs排序算法的优化。 四、实战应用 了解了Lucene的内部机制后,我们可以根据实际项目需求,结合...

    lucene3.0.3搜索的使用示例

    这个"lucene3.0.3搜索的使用示例"压缩包文件很可能是为了帮助用户理解并学习如何在项目中应用Lucene 3.0.3版本的功能。 在Lucene 3.0.3中,主要包含了以下核心概念和知识点: 1. **索引(Indexing)**:这是Lucene...

    盘古分词、lucene3.0.3搜索的使用示例v1.3.zip

    《盘古分词与Lucene 3.0.3在.NET 4.0中的应用实践》 盘古分词和Lucene是两个在文本处理和信息检索领域中至关重要的工具。盘古分词,作为一款优秀的中文分词系统,能够高效准确地对中文文本进行分词,为后续的数据...

    Lucene3.0.3+盘古分词 资源汇总

    《Lucene3.0.3与盘古分词:打造高效搜索引擎》 在信息技术日新月异的时代,搜索引擎已经成为我们获取信息的重要工具。Lucene,作为Apache软件基金会的一个开源项目,是Java语言实现的全文检索引擎库,为开发者提供...

    盘古分词、lucene3.0.3搜索的使用示例v1.2

    《盘古分词与Lucene 3.0.3在.NET 4.0中的应用实践》 盘古分词和Lucene是两个在中文信息处理领域广泛应用的工具,本示例将详细介绍如何在.NET 4.0环境中整合这两个组件,以实现高效的全文搜索功能,并新增了分页功能...

    盘古分词、lucene3.0.3搜索的使用示例.zip

    《盘古分词与Lucene 3.0.3在.NET 4.0中的应用实践》 盘古分词和Lucene是两个在文本处理和全文检索领域中至关重要的工具。本文将深入探讨如何在.NET 4.0环境中集成并使用这两个组件,以实现高效的文本分析和搜索引擎...

    Lucene3.0.3+盘古分词(证实可用,可指定使用自己的词库文件).rar

    在“Lucene3.0.3+盘古分词(证实可用,可指定使用自己的词库文件).rar”这个压缩包中,包含了实现这一功能所需的DLL文件和词库文件,这使得开发者可以轻松地在自己的项目中集成这一功能。 首先,我们要明白Lucene ...

    lucene 3.0.3.core.jar

    lucene3.0.3.core.jar文件,不用到apache官方网站下载17M的包,直接下载这个core就可以了。

    Lucene 3.0.3 API

    在 Lucene 3.0.3 版本中,我们看到了一系列重要的特性和改进,这些都极大地提升了其性能和易用性。 1. **索引过程**:Lucene 的索引过程涉及到将文档内容转换为倒排索引,这是一种高效的存储和检索方式。在 3.0.3 ...

    Lucene3.0分词系统.doc

    以下是对Lucene3.0分词系统中涉及的关键知识点的深入解析。 ### 英文分词原理 英文分词相较于中文来说较为简单,因为英文单词间通常以空格作为天然的分隔符。然而,为了提高搜索效率和准确性,Lucene3.0采用了更...

    lucene-3.0.3.zip

    《Apache Lucene 3.0.3:全文检索与搜索引擎核心技术详解》 Apache Lucene 是一个开源的全文检索库,由Java编写,提供强大的搜索功能。在这个3.0.3版本中,它继续展现了其在信息检索领域的强大性能和灵活性。Lucene...

    Lucene.NET v3.0.3 DEMO范例程序(含PanGu分词)

    这是Lucene.NET v3.0.3 DEMO范例程序(含PanGu分词),用C#语言编写的,同时对PanGu分词进行了整合,可以直接下载运行。 项目中还整理了一个后台任务线程监听范例,可以用作增量索引创建,但这个需要你自行加入相关...

    Lucene.net3.0.3源码

    Apache Lucene.Net 3.0.3 just passed a vote for release - our first official release since graduating from the incubator in August. A lot of work was put into porting and testing the code. We've ...

    Lucene SpellChecker3.0.2

    Lucene SpellChecker for Lucene 3.0.2

    lucene-smartcn-3.0.3.jar

    lucene-smartcn-3.0.3.jar

    Lucene实战(中文版第二版)对应Lucene版本

    此资源对应的是Lucene 3.0.3版本,这是Lucene发展历史中的一个重要里程碑。 在Lucene 3.0.3版本中,包含了以下关键知识点: 1. **索引构建**:Lucene的核心功能之一就是快速构建倒排索引。这个版本中,你可以学习...

    Apache-Lucene.Net-3.0.3-RC2

    Lucene.Net 3.0 最新源码 Lucene.net是Lucene的.net移植版本,是一个开源的全文检索引擎开发包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎。开发人员可以基于...

    lucene源码和教程

    lucene3.0.3源码和教程

Global site tag (gtag.js) - Google Analytics