您的位置:首页 > 其它

Lucene 如何实现高性能 GroupBy <一>

2010-11-24 10:14 344 查看
注:以下讲解代码均以Lucene.net 2.9.2为例。GroupBy效果应用(http://www.tradetuber.com/search?key=led

Lucene如果实现高性能的GroupBy、SortBy效果,我想这个应该是Lucener(Lucene使用者简称Lucener)遇到的最头大的问题。

Lucene各个方面表现都很优异,唯独在GroupBy及SortBy方面显得蹩脚,那么接下来的文章中我将为Lucener讲解如何更好的解决这两大问题。

1.GroupBy


要实现GroupBy,我们应该从哪下手? 如何下手?

从哪下手:从Collector类下手,Collector类相当于一个收集器,它收集的结果集是一个 ScoreDoc集合,ScoreDoc是DocID(文档ID)与Score(该文档得分)的一个对应关系,然后Lucene会使用移位运算等算法比较所有DocID的得分,并得到前多少条(pageSize*pageIndex)记录。

如何下手:当然是在逐个比较DocID的得分时注入相应的代码。

Collect

public override void Collect(int doc)
{
float score = scorer.Score();

//判断分组字段值是否已经存在,存在则返回,不存在继续,这样便保证了被分组字段对应的值有且仅出现一次。
if(_Dictionary.ContainsKey(dict[doc]))
return;

// This collector cannot handle these scores:
System.Diagnostics.Debug.Assert(score != float.NegativeInfinity);
System.Diagnostics.Debug.Assert(!float.IsNaN(score));

totalHits++;
if (score <= pqTop.score)
{
// Since docs are returned in-order (i.e., increasing doc Id), a document
// with equal score to pqTop.score cannot compete since HitQueue favors
// documents with lower doc Ids. Therefore reject those docs too.
return;
}
pqTop.doc = doc + docBase;
pqTop.score = score;
pqTop = (ScoreDoc)pq.UpdateTop();
}


写到这里,新的问题又产生了!

从上面的代码我们不难看出,虽然实现了GroupBy(假设我们按照公司ID来进行分组,每个公司只能出现一个产品),但是无法保证该产品是该公司得分最高的产品,这样也就影响了公司对应的产品排名。

e.g.

A公司(2个产品),得分依次为 0.12、0.33

B公司(2个产品),得分依次为 0.23、0.31

按照理论上,A公司一定排在B公司前面,因为A公司产品最高得分为0.33,B公司产品最高得分0.31分,按照上面的代码,有可能B公司就排在A公司前面了,当得分为0.12的产品先出现,那么A公司对应的最大产品分数就是0.12了,A公司就排在B公司之后了。

针对上述问题,我们仅仅在Collect方法注入代码是无法实现的,我们还需要结合 “结果集得分排序” 来解决上述问题,这时我们需要看看这个类(Lucene--Util--PriorityQueue.cs)。

PriorityQueue这个类是用来干什么的呢?它是用来对搜索结果按照得分高低进行顺序排列,并返回你需要的记录数的 ScoreDoc = {Doc, Score}。那接下来我们就一起研究研究它。

此篇完,下一篇将接着此篇继续为大家讲解 Lucene 如何实现高性能 GroupBy<二>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: