OpenBitSet和OpenBitSetIterator在TermRangeQuery中的运用
在MultiTermQuery 的rewrite方法中,如果 if (pendingTerms.size() >= termCountLimit || docVisitCount >= docCountCutoff) 的就会使用MultiTermQueryWrapperFilter,如果查询出来的term的总数目大于termCountLimit或者docVisitCount是 df ,如果df 大于docCountCutoff 则使用MultiTermQueryWrapperFilter,否则使用BooleanQuery,他们之间的关系是or的关系, MultiTermQueryWrapperFilter 使用OpenBitSet收集docId,使用OpenBitSetIterator还原docId
@Override
public Query rewrite(IndexReader reader, MultiTermQuery query) throws IOException {
// Get the enum and start visiting terms. If we
// exhaust the enum before hitting either of the
// cutoffs, we use ConstantBooleanQueryRewrite; else,
// ConstantFilterRewrite:
final Collection<Term> pendingTerms = new ArrayList<Term>();
final int docCountCutoff = (int) ((docCountPercent / 100.) * reader.maxDoc());
final int termCountLimit = Math.min(BooleanQuery.getMaxClauseCount(), termCountCutoff);
int docVisitCount = 0;
FilteredTermEnum enumerator = query.getEnum(reader);
try {
while(true) {
Term t = enumerator.term();
if (t != null) {
pendingTerms.add(t);
// Loading the TermInfo from the terms dict here
// should not be costly, because 1) the
// query/filter will load the TermInfo when it
// runs, and 2) the terms dict has a cache:
docVisitCount += reader.docFreq(t);
}
if (pendingTerms.size() >= termCountLimit || docVisitCount >= docCountCutoff) {
// Too many terms -- make a filter.
Query result = new ConstantScoreQuery(new MultiTermQueryWrapperFilter<MultiTermQuery>(query));
result.setBoost(query.getBoost());
return result;
} else if (!enumerator.next()) {
// Enumeration is done, and we hit a small
// enough number of terms & docs -- just make a
// BooleanQuery, now
BooleanQuery bq = new BooleanQuery(true);
for (final Term term: pendingTerms) {
TermQuery tq = new TermQuery(term);
bq.add(tq, BooleanClause.Occur.SHOULD);
}
// Strip scores
Query result = new ConstantScoreQuery(new QueryWrapperFilter(bq));
result.setBoost(query.getBoost());
query.incTotalNumberOfTerms(pendingTerms.size());
return result;
}
}
} finally {
enumerator.close();
}
}
收集的docId的代码 调用如图所示
先new 一个OpenBitSet,大小是查询出来的当前segemt中最大文档的数目,然后通过
SegmentTermDocs 的public int read(final int[] docs, final int[] freqs)
这个方法读取docId和frg,然后 通过for循环
for(int i=0;i<count;i++) {
bitSet.set(docs[i]);
}
把docId放到OpenBitSet里面
代码如下和注释如下
public DocIdSet getDocIdSet(IndexReader reader) throws IOException {
//返回TermRangeTermEnum对象,这个对象先用用小的那个string new一个term,然后定位到tis文件,while循环读取term信息,然后去frg文件里面读取docId,在while循环里面,通过SegmentTermDocs读取frg文件的docId和frg。
final TermEnum enumerator = query.getEnum(reader);
try {
// if current term in enum is null, the enum is empty -> shortcut
if (enumerator.term() == null)
return DocIdSet.EMPTY_DOCIDSET;
// else fill into a OpenBitSet
final OpenBitSet bitSet = new OpenBitSet(reader.maxDoc());
final int[] docs = new int[32];
final int[] freqs = new int[32];
// new 一个SegmentTermDocs的实例,会调用它的read方法读取docId
TermDocs termDocs = reader.termDocs();
try {
int termCount = 0;
do {
Term term = enumerator.term();
if (term == null)
break;
termCount++;
SegmentTermDocs 在frg文件里面seek到term的对应的docid的开始位置
termDocs.seek(term);
while (true) {
// 读取docId,一次读取到32 个docId到 docs数组里面,如果没有32个则读取实际的数目
final int count = termDocs.read(docs, freqs);
if (count != 0) {
for(int i=0;i<count;i++) {
bitSet.set(docs[i]);
}
} else {
break;
}
}
} while (enumerator.next());
query.incTotalNumberOfTerms(termCount);
} finally {
termDocs.close();
}
return bitSet;
} finally {
enumerator.close();
}
}
enumerator.next()方法截图如下,enumerator是TermRangeTermEnum,会调用父类的FilteredTermEnum next方法。
FilteredTermEnum的next方法如下,他会调用actualEnum读取tis文件里面的下一个term,然后调用termCompare 方法,termCompare 这个方法是抽象方法,留给子类实现,
TermRangeTermEnum方法的实现逻辑是和右边的区间的term做一个比较,看查询的term是否超出区间
public boolean next() throws IOException {
if (actualEnum == null) return false; // the actual enumerator is not initialized!
currentTerm = null;
while (currentTerm == null) {
if (endEnum()) return false;
if (actualEnum.next()) {
Term term = actualEnum.term();
if (termCompare(term)) {
currentTerm = term;
return true;
}
}
else return false;
}
currentTerm = null;
return false;
}
还原是在ConstantScorer的nextDoc方法调用的如下图
public int nextDoc() throws IOException {
return docIdSetIterator.nextDoc();
}
- 大小: 34.1 KB
- 大小: 41.4 KB
- 大小: 9.7 KB
- 大小: 37.8 KB
- 大小: 32.2 KB
分享到:
相关推荐
我们可以使用OpenBitSet来缓存删除的文档,然后在FilterIndexReader中对其进行过滤。 索引更新是Lucene中的一种重要机制,用于实时更新索引中的文档。我们需要根据实际情况选择合适的删除方式,并使用...
例如,可以创建一个自定义的`MyFilterIndexReader`,它保存一个位集(`OpenBitSet`)来记录已被删除的文档,并在`numDocs()`等方法中调整结果以排除这些文档。 ```java public class MyFilterIndexReader extends...
源头 - 分布式位图索引原语 注意:该项目目前作为概念证明存在。 虽然我信任索引器,但仍有大量性能和... 我已经从非常出色的OpenBitSet (从 Lucene 复制)和一个包装了byte[]数组的简单位图构建了参考位图。源头哈
【岗位说明】酒店各个岗位职责
机械设计注塑件水口冲切码盘设备_step非常好的设计图纸100%好用.zip
【岗位说明】公司各部门组织架构和岗位职责
使用YOLOv5和LPRNet进行车牌检测+识别(CCPD数据集)车牌识别项目(CCPD数据集)这个项目是利用YOLOv5和LPRNet对CCPD车牌进行检测和识别。之前一直在学习OCR相关的东西,就想着能不能做一个车牌识别的项目出来,之前也准备好车牌识别。我的打算是做一个轻量级的车牌识别项目,用YOLOv5进行车牌检测,用LPRNet进行车牌识别。目前仅支持识别蓝牌和绿牌(新能源车牌)等中国车牌。后续如果添加数据,可以再继续改装,可支持更多场景和更多类型车牌,提高识别准确率!主要参考以下四个仓库Githubhttps://github.com/ultralytics/yolov5Githubhttps ://github.com/sirius-ai/LPRNet_Pytorchhttps://gitee.com/reason1251326862/plate_classificationhttps://github.com/kiloGrand/License-Plate-Recognition如果对YOLOv5不熟悉源码的同学可以先看看我写的YOLOv5讲解
基于.net的医院信息管理系统(C#)。资源来源于网络分享,如有侵权请告知!
【岗位说明】营销中心高级经理岗位职责
环戊二烯行业分析:2024年全球环戊二烯市场销售额达到了8.83亿美元 环戊二烯,这一独特的化学品,在聚合物、制药、弹性体等多个领域展现出了广泛的应用前景。随着全球经济的持续增长和技术的不断进步,环戊二烯市场需求不断攀升。然而,面对复杂多变的市场环境和日益激烈的竞争,如何准确把握市场脉搏,制定有效的市场策略成为企业面临的关键问题。本文将带您深入了解全球环戊二烯市场的现状、趋势及机遇,为您的成功之路提供有力支持。 市场概况: 根据QYR(恒州博智)的统计及预测,2024年全球环戊二烯市场销售额达到了8.83亿美元,这一数字不仅彰显了市场的庞大规模,更预示着其强劲的增长势头。预计至2031年,市场规模将进一步扩大至12.25亿美元,年复合增长率(CAGR)高达4.8%。亚洲作为最大的市场,占有约45%的份额,展现出强劲的区域增长潜力。 技术创新与趋势: 技术创新是推动环戊二烯市场发展的核心动力。随着环保意识的提高和可持续发展理念的深入人心,市场对环保型环戊二烯产品的需求日益增长。同时,新型催化剂和合成技术的研发,为环戊二烯的生产和应用带来了更多可能性。 应用领域与细分市场: 环戊二烯在树脂
配电柜光按钮检测图像数据集,数据集总共700张左右图片,标注为VOC格式。内容来源于网络分享,如有侵权请联系我删除。另外如果没有积分的同学需要下载,请私信我。
【岗位说明】销售人员岗位职责说明书
【岗位说明】市场与销售类岗位说明书
【岗位说明】销售部各职务详细岗位说明书描述
c语言运行程序
multisim声控流水灯仿真电路设计 功能: 制作一个声控的LED流水灯电路,20只灯珠依次点亮,当 音量高时流水灯切快,当音调低时流水灯切慢。 1.制作拾音整形电路; 2.制作LED驱动电路; 3.制作系统所需的直流电源; 资料包含:仿真源文件+原理说明书(仅参考)+演示视频
基于Python的南京二手房数据采集及可视化分析1 内容简介首先通过爬虫采集链家网上所有南京二手房的房源数据,对文献采集到的数据进行清理然后,对清理后的数据进行可视化背后的分析,探索隐藏在大量数据的规律最后,采用一个全新的对所有二手房数据进行算法分析,并根据奥迪分析的结果,将这些房源大致分类,以对所有数据的百年总结。通过上述分析,我们可以了解目前二手房各项基本情况特征及房源分配情况,帮助我们进行购房决策。2 应用技术介绍1)Python网络爬虫技术请求美丽的汤2)Python分析技术NumpyMatplotlib熊猫3)k-means聚类算法4)高德地图开发者应用JS API3 数据采集及数据清洗3.1 数据采集该部分通过网络爬虫程序抓取网上所有南京二手房的数据,收集原始数据,作为整个数据分析的基石。3.1.1链家网网站结构分析链家网二手房主页界面如图1、图2,主页上面红色方塔位置显示了目前南京房在售房源的各区域位置名称,中间红色方塔位置显示了房源的总数量,下面红色方方框显示了二手房源信息,该红色方框区域包含了二手房源页面的UR
西门子变频器 SINAMICS STARTER V5.6 HF1 软件 STARTER V56 STARTERV56HF1 ISO 001
激光熔覆仿真comsol通过激光进行熔覆工艺进行仿真,对温度与应力进行研究 采用COMSOL中的固体传热等物理场进行耦合仿真 对激光熔覆工艺完成后的温度分布与应力分布以云图形式输出,并研究某一点温度与应力随时间变化的曲线关系,温度梯度随时间变化的曲线关系,第三主应力随时间变化的曲线关系。 以及整个激光熔覆工艺过程的动画。
RoboMaster 智能数据集标注工具RoboMaster 智能数据集标注工具基于[ Qt5+OpenCV(with OpenVINO) ],用于标注RoboMaster装甲板4个顶点的位置,灯条颜色,以及贴纸类型。开发中分支,建议下载release里的软件和源码本人的第一个Qt项目,写的不好的地方见谅项目介绍基于深度学习的自瞄准识别算法逐渐走进RoboMaster的赛场。相比于传统的视觉识别算法,基于深度学习的算法具有更强的鲁棒性和识别性,受到增强队伍的青睐。然而常规深度学习的目标检测算法只能识别出目标的映射,这给后续算法中的单目测距带来了困难。本项目希望能够建立一个方便的4点数据集标注工具,可以快速而准确的完成数据集的制作。主要功能亮点将标准装甲板贴纸图像添加到图片上,包括观察的一些结果。选点时局部放大,然后观察选点位置。智能预识别,弱人力。(需要带 OpenVINO 支持的 OpenCV,可以不用OpenVINO,但速度会变慢)图像的缩放与拖动。使用OpenVINO进行int8加速。(无OpenVINO时无法使用)一键自动标定所有图