9月7日-8日,相约 2023 腾讯全球数字生态大会!聚焦产业未来发展新趋势! 了解详情
写点什么

5 分钟了解 lucene

  • 2020-02-12
  • 本文字数:7566 字

    阅读完需:约 25 分钟

5分钟了解lucene
本文通俗地介绍了Lucene全文检索的内容及工作原理,以及索引的结构,旨在让以前未了解过Lucene的读者在能在短时间内对Lucene有简单认知,未介绍具体代码,读完本文可知道Lucene是什么,有哪些具体应用,我们一直说的索引是什么。


<section class="" style="margin: 0px; padding: 0px; max-width: 100%; color: rgb(51, 51, 51); font-family: -apple-system-font, system-ui, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif; font-size: 17px; font-variant-ligatures: normal; letter-spacing: 0.544px; orphans: 2; text-align: justify; white-space: normal; widows: 2; box-sizing: border-box !important; overflow-wrap: break-word !important;">    <section style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; width: 0.6em; display: inline-block; vertical-align: middle;"></section>
<section style="margin: 0px; padding: 0px 0px 0px 10px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; color: rgb(6, 154, 242); display: inline-block; font-weight: 700; vertical-align: middle;"> <section class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> Lucene介绍及应用</section> </section>

</section>


Apache Lucene是当下最为流行的开源全文检索工具包,基于JAVA语言编写。
目前基于此工具包开源的搜索引擎,成熟且广为人知的有Solr和Elasticsearch。2010年后Lucene和Solr两个项目由同一个Apache软件基金会的开发团队制作,所以通常我们看到的版本都是同步的。二者的区别是Lucene是工具包,而Solr是基于Lucene制作的企业级搜索应用。另外,我们常用的Eclipse,帮助系统的搜索功能也是基于Lucene实现的。


<section class="" style="margin: 0px; padding: 0px; max-width: 100%; color: rgb(51, 51, 51); font-family: -apple-system-font, system-ui, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif; font-size: 17px; font-variant-ligatures: normal; letter-spacing: 0.544px; orphans: 2; text-align: justify; white-space: normal; widows: 2; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <section style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; width: 0.6em; display: inline-block; vertical-align: middle;"></section>
<section style="margin: 0px; padding: 0px 0px 0px 10px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; color: rgb(6, 154, 242); display: inline-block; font-weight: 700; vertical-align: middle;"> <section class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> Lucene的两项工作</section> </section>

</section>


我们的生活物品中,汉语字典与全文索引是很相似的。我们拿拼音查字法举例,首先我们通过拼音找到我们要查字的页数,然后翻到该页,阅读这个字的详细解释。
在上面的例子中,我们提到了两个要素:一个是字典,另一个是查字的过程。对应到Lucene的功能上,一个是我们要建立一个字典,这个过程叫做建立索引,另一个是根据搜索词基于索引进行查询。


<section class="" style="margin: 0px; padding: 0px; max-width: 100%; color: rgb(51, 51, 51); font-family: -apple-system-font, system-ui, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif; font-size: 17px; font-variant-ligatures: normal; letter-spacing: 0.544px; orphans: 2; text-align: justify; white-space: normal; widows: 2; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <section class="" style="margin: 20px 0px 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <section class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; border-color: initial; border-style: none; border-width: 0px;"> ## **建立索引** </section> </section></section>


**1. 文档的准备(Document)**
文档就是指我们要去搜索的原文。
**2. 分词组件(Tokenizer)**
将第一步的文档进行词语切割,去除标点,去除无用词,比如“是”,“的”等。常用的开源中文分词组件有MMSEG4J、IKAnalyzer等。切割后的词语我们称为词元(Token)。
**3. 语言处理(Linguistic Processor)**
将上一步的获得的词元进行处理,比如英文的大写转小写,复数变单数,过去时分词转原形等。此时得到的结果,被称作词(Term)
**4. 索引组件**
索引组件将上步得到的词,生成索引和词典,存储到磁盘上。索引组件先将Term变成字典,然后对字典进行排序,排序后对相同的词进行合并,形成倒排列表。每个词在列表中存储了对应的文档Id(Document Frequency)以及这个词在这个文档中出现了几次(Term Frequency)。


<section class="" style="margin: 0px; padding: 0px; max-width: 100%; color: rgb(51, 51, 51); font-family: -apple-system-font, system-ui, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif; font-size: 17px; font-variant-ligatures: normal; letter-spacing: 0.544px; orphans: 2; text-align: justify; white-space: normal; widows: 2; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <section class="" style="margin: 20px 0px 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <section class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; border-color: initial; border-style: none; border-width: 0px;"> ## **搜索** </section> </section></section>


**1. 输入查询词**
**2. 词法分析及语言处理**
对输入的词进行拆分,关键字识别(AND,NOT)等。对拆分的词元进行语言处理,与建立字典时语言处理的过程相同。由关键字与处理后的词生成语法树。
**3. 搜索索引,获得符合语法树的文档**
如A and B not C形成的语法树,则会搜索包含A B C的文档列表,然后用A和B的文档列表做交集,结果集与C做差集,得到的结果,就是符合搜索条件的文档列表
**4. 根据相关性,对搜索结果排序**
通过向量空间模型的算法,得到结果的相关性。比较简单的实现描述如下:在建立索引的时候,我们得到了Document Frequency和Term Frequency,Term Frequency越高,说明文档的相关性越高;Document Frequency越高,说明相关性越弱。这个算法可以自己进行实现。
**5. 根据上面的排序结果,返回文档。**


<section class="" style="margin: 0px; padding: 0px; max-width: 100%; color: rgb(51, 51, 51); font-family: -apple-system-font, system-ui, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif; font-size: 17px; font-variant-ligatures: normal; letter-spacing: 0.544px; orphans: 2; text-align: justify; white-space: normal; widows: 2; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <section style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; width: 0.6em; display: inline-block; vertical-align: middle;"></section>
<section style="margin: 0px; padding: 0px 0px 0px 10px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; color: rgb(6, 154, 242); display: inline-block; font-weight: 700; vertical-align: middle;"> <section class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;">索引结构</section> </section>

</section>


Lucene的索引结构是有层次结构的。我们以下图为例






<section class="" style="margin: 0px; padding: 0px; max-width: 100%; color: rgb(51, 51, 51); font-family: -apple-system-font, system-ui, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif; font-size: 17px; font-variant-ligatures: normal; letter-spacing: 0.544px; orphans: 2; text-align: justify; white-space: normal; widows: 2; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <section class="" style="margin: 20px 0px 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <section class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; border-color: initial; border-style: none; border-width: 0px;"> ## **索引(Index)** </section> </section></section>


如果拿数据库做类比,索引类似于数据库的表。
在Lucene中一个索引是放在一个文件夹中的。所以可以理解索引为整个文件夹的内容。


<section class="" style="margin: 0px; padding: 0px; max-width: 100%; color: rgb(51, 51, 51); font-family: -apple-system-font, system-ui, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif; font-size: 17px; font-variant-ligatures: normal; letter-spacing: 0.544px; orphans: 2; text-align: justify; white-space: normal; widows: 2; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <section class="" style="margin: 20px 0px 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <section class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; border-color: initial; border-style: none; border-width: 0px;"> ## **段(Segment)** </section> </section></section>


如果拿数据库做类比,段类似于表的分区。
索引下面引入了Segment 的概念,一个索引下可以多个段。当flush或者commit时生成段文件。截图中有0,1两个段。segments.gen和segments_5是段的元数据文件,它们保存了段的属性信息。其他的文件对应的就是各段的文件,稍后会详细说明各文件的用处。
索引的写入是顺序的,只能被追加,不能被修改。当索引要删除时,在.del文件中写入对应的docId。查询的时候会过滤到此docId。另外索引的修改,是对Document进行删除后做的追加。这种设计保证了高吞吐量。
分段的设计能保证查询的高效,当段太大时,查询会产生很大的IO消耗。段太小,则需要查询的段太多。所以lucene对段进行了合并,另外删除的数据也是在合并过程中过滤掉的。4.0之前的默认的合并策略为LogMergePolicy,这个策略会合并小于指定值的相邻段,如果两个相邻段,一个大小为1G,一个大小为1k,则会重写1G的文件会占用很大资源。4.0之后默认策略改为了TieredMergePolicy,这个策略会先按分段大小进行排序,对段进行删除比计算,优先合并小的分段。当系统闲暇的时候,才对大分段进行合并。




<section class="" style="margin: 0px; padding: 0px; max-width: 100%; color: rgb(51, 51, 51); font-family: -apple-system-font, system-ui, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif; font-size: 17px; font-variant-ligatures: normal; letter-spacing: 0.544px; orphans: 2; text-align: justify; white-space: normal; widows: 2; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <section class="" style="margin: 20px 0px 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <section class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; border-color: initial; border-style: none; border-width: 0px;"> ## **文档(Document)** </section> </section></section>


如果拿数据库做类比,文档类似于数据的一行。
Document是索引的基本单位。一个段可以有多个Document




<section class="" style="margin: 0px; padding: 0px; max-width: 100%; color: rgb(51, 51, 51); font-family: -apple-system-font, system-ui, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif; font-size: 17px; font-variant-ligatures: normal; letter-spacing: 0.544px; orphans: 2; text-align: justify; white-space: normal; widows: 2; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <section class="" style="margin: 20px 0px 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <section class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; border-color: initial; border-style: none; border-width: 0px;"> ## **域(Field)** </section> </section></section>


如果拿数据库做类比,域相当于表的字段。
Doument里可以有多个Field。Lucene提供多种不同类型的Field,例如StringField、TextField、LongFiled或NumericDocValuesField等。


<section class="" style="margin: 0px; padding: 0px; max-width: 100%; color: rgb(51, 51, 51); font-family: -apple-system-font, system-ui, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif; font-size: 17px; font-variant-ligatures: normal; letter-spacing: 0.544px; orphans: 2; text-align: justify; white-space: normal; widows: 2; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <section class="" style="margin: 20px 0px 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <section class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; border-color: initial; border-style: none; border-width: 0px;"> ## **词(Term)** </section> </section></section>


Term是索引的最小单位。Term是由Field经过Analyzer(分词)产生。


<section class="" style="margin: 0px; padding: 0px; max-width: 100%; color: rgb(51, 51, 51); font-family: -apple-system-font, system-ui, 'Helvetica Neue', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Microsoft YaHei', Arial, sans-serif; font-size: 17px; font-variant-ligatures: normal; letter-spacing: 0.544px; orphans: 2; text-align: justify; white-space: normal; widows: 2; box-sizing: border-box !important; overflow-wrap: break-word !important;"> <section style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; width: 0.6em; display: inline-block; vertical-align: middle;"></section>
<section style="margin: 0px; padding: 0px 0px 0px 10px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; color: rgb(6, 154, 242); display: inline-block; font-weight: 700; vertical-align: middle;"> <section class="" style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;">段的文件说明</section> </section>

</section>


第三小节详细描述了段的设计和合并策略,以下详细讲解一些段文件的内容。
segments_N保存了此索引包含多少个段,每个段包含多少篇文档。
**\*.fnm**
保存了此段包含了多少个域,每个域的名称及索引方式。
**\*.fdx,*.fdt**
保存了此段包含的所有文档,每篇文档包含了多少域,每个域保存了那些信息。
**\*.tvx,*.tvd,*.tvf**
保存了此段包含多少文档,每篇文档包含了多少域,每个域包含了多少词,每个词的字符串,位置等信息。
**\*.tis,*.tii**
保存了词典(Term Dictionary),也即此段包含的所有的词按字典顺序的排序。
**\*.frq**
保存了倒排表,也即包含每个词的文档ID列表。
**\*.prx**
保存了倒排表中每个词在包含此词的文档中的位置
**\*.del**
前面讲段的时候有提到,用来是存储删掉文档id的。
复制代码


本文转载自宜信技术学院网站。


原文链接:http://college.creditease.cn/detail/187


活动推荐:

2023年9月3-5日,「QCon全球软件开发大会·北京站」 将在北京•富力万丽酒店举办。此次大会以「启航·AIGC软件工程变革」为主题,策划了大前端融合提效、大模型应用落地、面向 AI 的存储、AIGC 浪潮下的研发效能提升、LLMOps、异构算力、微服务架构治理、业务安全技术、构建未来软件的编程语言、FinOps 等近30个精彩专题。咨询购票可联系票务经理 18514549229(微信同手机号)。

2020-02-12 15:34702

评论

发布
暂无评论
发现更多内容

React高级特性之Context

夏天的味道123

React

开发培训学习后工作好找吗?

小谷哥

遗留代码处理技巧与案例演示

京东科技开发者

数据结构 重构 代码重构 遗留代码 耦合

深圳哪所前端培训机构比较靠谱

小谷哥

融云「百幄」之视频会议和直播,让办公桌无限延伸

融云 RongCloud

直播 视频会议 通讯

实现Promise的原型方法--前端面试能力提升

helloworld1024fd

JavaScript

工业互联网新引擎——灵雀云 × 英特尔 5G融合边缘云解决方案

York

云原生 5G 边缘计算 架构设计 云边端协同

如何实现对象存储?

MatrixOrigin

数据库 分布式数据库 对象存储 MatrixOrigin MatrixOne

react-Suspense工作原理分析

夏天的味道123

React

react组件深度解读

xiaofeng

React

云栖大会|未来,万物皆是计算机?

云布道师

云计算 阿里云 2022云栖大会

DevEco Device Tool 3.1 Beta1版本发布,产品化配置优化添加自定义烧录器

HarmonyOS开发者

HarmonyOS

enca 1.19 移植指南 (openEuler 20.03 LTS SP1)

openEuler

centos 开源 操作系统 openEuler enca

女生参加前端培训,学习不如男生吗?

小谷哥

CRAFTS:端对端的场景文本检测器

合合技术团队

人工智能 深度学习 文字识别 端口 文本检测

云资源管理平台有哪些?重点推荐哪家?

行云管家

云计算 云服务 云资源 云管理

react进阶用法完全指南

xiaofeng

React

「Go工具箱」web中想做到cookie值安全?securecookie库的使用和实现原理

Go学堂

golang 开源 程序员 Cookie WEB安全

js手写题汇总(面试前必刷)

helloworld1024fd

JavaScript

大数据培训学习合适吗?

小谷哥

Nydus | 容器镜像基础

SOFAStack

Nydus

React高级特性之Render Props

夏天的味道123

React

React组件通信

xiaofeng

React

前端一面必会手写面试题指南

helloworld1024fd

JavaScript

大学生想进大厂是通过自学还是java培训

小谷哥

几个常见的js手写题,你能写出来几道

helloworld1024fd

JavaScript

湘潭等级测评机构有哪些?排名是怎样?

行云管家

等保 等级保护 等保测评 等保测评机构

线上kafka消息堆积,consumer掉线,怎么办?

Java永远的神

Java kafka 程序员 程序人生 消息中间件

大咖圆桌|研发想要降本增效?来听听专家们的前沿洞见

万事ONES

Git本地提交代码推送远程并未统计贡献量问题分析

Andy

线上直播 | 未来金融研究所——以应用为中心,重塑金融研发效率

CODING DevOps

云原生 金融

  • 扫码添加小助手
    领取最新资料包
5分钟了解lucene_行业深度_田梁_InfoQ精选文章