lucene 多路归并算法
来源:互联网 发布:中国电视剧 国外 知乎 编辑:程序博客网 时间:2024/06/05 18:02
对于分布式存储的数据库(如elasticsearch),在执行完一次查询后,需要将多个节点的数据归并到一起(每个节点的数据已经排好序),这个时候需要使用到多路归并算法,下面以lucene的实现代码为例子讲解。
1、每个数据节点上的数据作为一个TopDocs,那么多个数据节点上的topDocs组成一个TopDocs[]
2、将TopDocs[]添加到一个最大堆中,堆中的每个节点对应一个topDocs,堆中每个节点大小的比较标准以每个topdocs中的hitIndex指针指向的doc的分数为标准。3、将最大堆的根节点移除出来作为一个topDocs,该topDocs中的hitIndex指针指向的doc肯定是最大的,将该doc放入到返回结果的数组中。hitIndex是否已经遍历完该topDocs,如果没有遍历完,需要将该topDocs重新加回到最大堆中
4、判断堆中是否还有节点,如果有,继续第3步
详细代码
public static TopDocs merge(Sort sort, int start, int size, TopDocs[] shardHits) throws IOException {
final PriorityQueue<ShardRef> queue;
if (sort == null) {
//构造最大堆
queue = new ScoreMergeSortQueue(shardHits);
} else {
queue = new MergeSortQueue(sort, shardHits);
}
int totalHitCount = 0;
int availHitCount = 0;
float maxScore = Float.MIN_VALUE;
for(int shardIDX=0;shardIDX<shardHits.length;shardIDX++) {
final TopDocs shard = shardHits[shardIDX];
// totalHits can be non-zero even if no hits were
// collected, when searchAfter was used:
totalHitCount += shard.totalHits;
if (shard.scoreDocs != null && shard.scoreDocs.length > 0) {
availHitCount += shard.scoreDocs.length;
//将TopDocs[] 中的topDocs逐个添加到最大堆中,判断大小的标准是topDocs中hitIndex指向的doc的分数大小
queue.add(new ShardRef(shardIDX));
maxScore = Math.max(maxScore, shard.getMaxScore());
//System.out.println(" maxScore now " + maxScore + " vs " + shard.getMaxScore());
}
}
if (availHitCount == 0) {
maxScore = Float.NaN;}
final ScoreDoc[] hits;
if (availHitCount <= start) {hits = new ScoreDoc[0];
} else {
hits = new ScoreDoc[Math.min(size, availHitCount - start)];
int requestedResultWindow = start + size;
int numIterOnHits = Math.min(availHitCount, requestedResultWindow);
int hitUpto = 0;
while (hitUpto < numIterOnHits) {
assert queue.size() > 0;
//获取最大堆中的根节点
ShardRef ref = queue.pop();
//拿到最大的doc,放入到hits中
final ScoreDoc hit = shardHits[ref.shardIndex].scoreDocs[ref.hitIndex++];
hit.shardIndex = ref.shardIndex;
//如果达到了start后,才放入到hits(分页)
if (hitUpto >= start) {
hits[hitUpto - start] = hit;
}
hitUpto++;
if (ref.hitIndex < shardHits[ref.shardIndex].scoreDocs.length) {
queue.add(ref);
}
}
}
if (sort == null) {
return new TopDocs(totalHitCount, hits, maxScore);
} else {
return new TopFieldDocs(totalHitCount, hits, sort.getSort(), maxScore);
}
}
//最大堆中各节点判断大小的标准
@Override
public boolean lessThan(ShardRef first, ShardRef second) {
assert first != second;
//每个节点上hitIndex指向的doc的score
final float firstScore = shardHits[first.shardIndex][first.hitIndex].score;
final float secondScore = shardHits[second.shardIndex][second.hitIndex].score;
if (firstScore < secondScore) {
return false;
} else if (firstScore > secondScore) {
return true;
} else {
// Tie break: earlier shard wins
if (first.shardIndex < second.shardIndex) {
return true;
} else if (first.shardIndex > second.shardIndex) {
return false;
} else {
// Tie break in same shard: resolve however the
// shard had resolved it:
assert first.hitIndex != second.hitIndex;
return first.hitIndex < second.hitIndex;
}
}
}
0 0
- lucene 多路归并算法
- 多路文件归并,败者树算法
- 二路归并算法
- 二路归并算法
- 二路归并算法
- 二路归并算法
- 两路归并排序算法
- k-路归并的算法
- 2-路归并排序算法
- 二路归并排序算法
- 2路归并排序算法
- 二路归并排序算法
- 《两路归并排序算法》
- 二路归并排序算法
- Lucene算法
- 败者树实现多路平衡归并外部排序算法
- 纯Java实现的多路归并快速排序算法
- 败者树实现多路平衡归并外部排序算法
- 【python】批量扫描IP地址80/8080端口
- MQTT协议简记
- 工具类--本地路径图片转字节
- Base64算法 编码过程和原理
- Magento调用New Arrivals 新品上架产品实例
- lucene 多路归并算法
- JSON.parse()和JSON.stringify()使用介绍
- Anroid studio遇到的问题4---Gradle DSL method not found runProguard
- jqGrid初始化自带选中
- Joda 日期类简单的获取当前完整日期和当前日子的用法
- [CSS3] 新增属性用法整理
- 第三章 数据和C(二)
- 什么是防火墙的入站规则和出站规则.如何新建入站规则
- spring aop 利用JoinPoint获取参数的值和方法名称