Lucene搜索核心代码TermInfosReader
TermInfosReader类是Lucene搜索的核心代码,所有的搜索最终都是落到通过term查询,TermInfosReader里定义了支持的基础的term查询功能。
前置知识:
词元字典文件(tis):
文件描述:
文件中的term按照从小到大排序,排序规则:先按照属性名排,如果属性名相同,再按照词元内容排,简单的字符比较。tis文件中存储的词元列表按照IndexInterval分成多个块,后面在查询逻辑里叙述通过块如何优化搜索。
文件结构:
TermInfos --> <TermInfo>TermCount
TermInfo --> <Term, DocFreq, FreqDelta, ProxDelta, SkipDelta>
词元索引文件(tii):
文件描述:
tii文件是tis文件的索引文件,按照tis文件中存储的IndexInterval间隔存储tii文件,tii文件中词元内容和tis一样,除了词元外,tii文件中每个词元附加一个IndexDelta数据,存储了该词元在tis文件中的位置,
文件结构:
TermIndices --> <TermInfo, IndexDelta>IndexTermCount
IndexDelta --> VInt // IndexDelta表示这个索引词元在tis文件中的具体位置,类似指针
核心方法一:
TermInfo get(Term term)
方法描述:
方法传入term,返回TermInfo,通过TermInfo里的freqPointer和proxPointer可以从.frq文件中取包含该词元的文档列表,和从.prx文件中取词元在每个文档中出现的位置。get方法是用于查询指定存在的term,如果term不存在这个方法返回一个null
逻辑描述:
系统初始化时将tii文件中的所有数据加载到内存中,具体是代码TermInfosReader里的indexTerms和indexInfos还有indexPointers变量中,indexTerms中存储.tii文件中所有的词元数据,indexInfos存储词元附加信息,比如词元在frq文件和prox文件中的相应数据的位置,indexPointers存储每个.tii文件中索引词元在.tis文件中的原始位置。这几个变量都是数组,按照下标一一对应。
词元都是从小到大排好顺序的,所以要搜索入参term在tis文件中的位置,就要从前往后一个一个遍历。
优化点1:
通过上面已经加载到内存中的tii文件数据可以优化这个查找过程,具体过程如下:
先通过参数term到indexTerms变量中找到一个比自己小而且是最接近的索引词元。在1.4里实现是通过二分查找
然后通过indexTerms、indexInfos、indexPointers这三个变量在下标上的对应关系找到这个最接近且比参数小的索引词元在tis文件中的原始位置,这个数据在indexInfos里有记录。
然后上面的从前往后一个一个遍历可以优化为从上面得到的索引词元开始往后遍历。
优化点2:
这里还有一个优化点,对于顺序查找且在同一个块内的词元时,其实不需要去索引词元列表里找下标,然后通过下标往后遍历,这时候可以直接通过第一次查询的词元(遍历的当前词元)的位置往后遍历。通过tii文件找也是为了找到一个和当前查询词元最接近的索引词元,现在这种场景下第一次查询的词元是最接近的,所以不需要在使用索引词元查找。
核心方法2:
SegmentTermEnum terms(Term term)
方法描述:
get方法查询指定的词元,terms方法查询匹配的多个词元,用于范围搜索场景,比如前缀查询、模糊查询等。terms方法是基于get方法来实现的,get方法还有个副作用,在执行get方法时会移动当前遍历的指针,如果查询到某个词元,则指针指向该词元,如果没有查询到词元,则把指针定位到与查询词元最近的一个比查询词元大的词元位置。
逻辑描述:
terms方法正是通过这个副作用来工作的,terms的代码很简单:
get(term);
return (SegmentTermEnum)getEnum().clone();
先通过get定位到最小的词元位置,然后返回以命中的最小词元为头的词元链表,调用方可以通过这个链表获取到所有相似的词元以及包含每个词元的文档列表。
Lucene搜索核心代码TermInfosReader的更多相关文章
- Lucene核心--构建Lucene搜索(上篇,理论篇)
2.1构建Lucene搜索 2.1.1 Lucene内容模型 一个文档(document)就是Lucene建立索引和搜索的原子单元,它由一个或者多个字段(field)组成,字段才是Lucene的真实内 ...
- Lucene系列六:Lucene搜索详解(Lucene搜索流程详解、搜索核心API详解、基本查询详解、QueryParser详解)
一.搜索流程详解 1. 先看一下Lucene的架构图 由图可知搜索的过程如下: 用户输入搜索的关键字.对关键字进行分词.根据分词结果去索引库里面找到对应的文章id.根据文章id找到对应的文章 2. L ...
- Ajax (Asynchronous javascript xml) 搜索框核心代码(JQuery) Ajax判断用户名存在核心代码 附:原生js的Ajax代码 其中有json的一句话解释
前端 <script type="text/javascript"> $(function(){ $("#tid").keyup(function( ...
- Lucene学习笔记: 五,Lucene搜索过程解析
一.Lucene搜索过程总论 搜索的过程总的来说就是将词典及倒排表信息从索引中读出来,根据用户输入的查询语句合并倒排表,得到结果文档集并对文档进行打分的过程. 其可用如下图示: 总共包括以下几个过程: ...
- Lucene学习总结之七:Lucene搜索过程解析
一.Lucene搜索过程总论 搜索的过程总的来说就是将词典及倒排表信息从索引中读出来,根据用户输入的查询语句合并倒排表,得到结果文档集并对文档进行打分的过程. 其可用如下图示: 总共包括以下几个过程: ...
- Lucene学习总结之七:Lucene搜索过程解析 2014-06-25 14:23 863人阅读 评论(1) 收藏
一.Lucene搜索过程总论 搜索的过程总的来说就是将词典及倒排表信息从索引中读出来,根据用户输入的查询语句合并倒排表,得到结果文档集并对文档进行打分的过程. 其可用如下图示: 总共包括以下几个过程: ...
- Lucene搜索方式大合集
package junit; import java.io.File; import java.io.IOException; import java.text.ParseException; imp ...
- lucene 搜索demo
package com.ljq.utils; import java.io.File; import java.util.ArrayList; import java.util.List; impor ...
- 【五子棋AI循序渐进】关于VCT,VCF的思考和核心代码
前面几篇发布了一些有关五子棋的基本算法,其中有一些BUG也有很多值得再次思考的问题,在框架和效果上基本达到了一个简单的AI的水平,当然,我也是初学并没有掌握太多的高级技术.对于这个程序现在还在优化当中 ...
随机推荐
- linux下编译安装MariaDB 10.4.7,解决错误:cannot access ‘/auth_pam_tool_dir’: No such file or directory
编译安装MariaDB 10.4.7,前面的步骤我就不复述了,一切正常没什么问题. 当执行到:scripts/mysql_install_db --basedir=/usr/local/mysql - ...
- iOS音频与视频的开发(一)-使用AVAudioPlayer播放音乐、使用AVPlayerViewController播放视频
iOS的多媒体支持非常强大,它提供了多套支持多媒体的API,无论是音频.视频的播放,还是录制,iOS都提供了多种API支持.借助于这些API的支持,iOS应用既可以查看.播放手机相册中的照片.视频,也 ...
- REST API接口测试
背景介绍 为什么要做借口测试? 很多系统关联都是基于接口来实现的,接口测试可以将复杂的系统关联进行简化. 接口功能比较单一,能够比较好的进行测试覆盖,也相对容易实现自动化持续集成. 接口相当于界面功能 ...
- CodeForces-1253B(贪心+模拟)
题意 https://vjudge.net/problem/CodeForces-1253B 把一个序列划成几段,使得每一段都是+x在-x前面,二者均要有. 问划成几段,每一段的大小是多少. 思路 用 ...
- C++学习二 vector的用法(使用sort对于vector排序)
一.vector的介绍 vector是C++里面的一个容器,也是我们数学上面理解的向量,有一些比较常见的操作. 二.vector的定义 #include<vector> using nam ...
- ACM-ICPC 2018 焦作网络赛
题目顺序:A F G H I K L 做题链接 A. Magic Mirror 题意:判断 给出的 字符串 是否等于"jessie",需要判断大小写 题解:1.用stl库 tolo ...
- 如何在Pycharm中添加新的模块
在使用Pycharm编写程序时,我们时常需要调用某些模块,但有些模块事先是没有的,我们需要把模块添加上去. 最近在学习爬虫,写了下面几行代码: 结果出现错误 错误ModuleNotFoundError ...
- 《为什么说Redis是单线程的以及Redis为什么这么快!》
为什么说Redis是单线程的以及Redis为什么这么快! 一.前言 近乎所有与Java相关的面试都会问到缓存的问题,基础一点的会问到什么是“二八定律”.什么是“热数据和冷数据”,复杂一点的会问到缓 ...
- tf.summary.scalar()和tf.summary.histogram
用法: 1.tf.summary.scalar 用来显示标量信息,其格式为: tf.summary.scalar(tags, values, collections=None, name=None) ...
- UVA11374 Airport Express 正反两次最短路
问题描述 洛谷(有翻译) 吐槽 一道坑题. 如何对待商务票 因为商务票只有一张,所以在\(k\)条边中只有一条边会被选中,很显然,最后这条边会被枚举. 如何选择使用商务票的边 假设我们正在枚举这条边, ...