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
写到这里,新的问题又产生了!
从上面的代码我们不难看出,虽然实现了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<二>。
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<二>。
相关文章推荐
- Lucene 如何实现高性能 GroupBy <一>
- Lucene 如何实现高性能 GroupBy <二>
- Lucene 如何实现高性能 GroupBy <二>
- 如何实现具有层次结构的 TreeView <一> (WPF/TreeView/Style/Template)
- 如何用<Enter>键代替<Tab>键实现光标焦点转移?
- 如何实现批处理的连续调用?<一星>
- ThreadPoolExecutor核心实现原理和源码解析<一>
- SCSI命令下发方式<续>:对NVMe硬盘如何实现SCSI命令转换?
- 如何解决服务器CPU使用率过高的问题<一>
- 短信猫软件的实现(C#)<一>熟悉串口
- XAF 如何扩展应用程序模型(How to: Extend the Application Model )<一> ListView显示页脚信息
- 经典算法问题的java实现<一>
- 【技术讨论】从弹弹堂说起,如何用2D物理引擎编写一个游戏<一>
- 智能指针里弱引用应该如何实现?(WeakReference/WeakPtr<T>)
- quick-cocos2d-x的热更新机制实现<一>前言
- 如何实现4个<div>在同一行上
- 如何实现具有层次结构的 TreeView <四> (WPF/TreeView/Style/Template)
- java实现一个socks5代理 <一>了解socks5协议
- 在cocos2d-x 3.2下利用UI下面的控件模仿实现GridView部分效果<一>实现构思
- 模拟实现通讯录 <一><静态方法>