
<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(微信同手机号)。
更多内容推荐
已获千赞,进阶学习资料!
深入浅出索引(上)
2021-08-02
搜索引擎的基本架构
2022-09-10
软件测试 | 测试人员必须掌握的测试用例
搜索微信公众号:TestingStudio 霍格沃兹的干货都很硬核
2022-11-16
完美收官
为期两天的比赛结束了,收获到了很多。有新的认知,也重新梳理了一下之前学习的内容。最重要的是,和好多之前只在微信中认识的朋友们见面了。哈哈哈哈。
2021-07-04
一文讲透产品经理如何用好 ChatGPT
我基于GPT-4,梳理了帮助产品经理全流程提效的方法,整理了一些prompt,本文旨在分享这些收获,希望能抛砖引玉。
2023-04-23
☕【JVM 技术指南】「理论总结笔记」Java 虚拟机垃圾回收认知和调优的"思南(司南)"【下部】
(完结撒花1-52系列)☕【JVM技术指南】「JVM总结笔记」Java虚拟机垃圾回收认知和调优的"思南(司南)"【上部】
2021-09-14
工作多年,技术认知不足,个人成长慢,职业发展迷茫,该怎么办?
2022-11-04
深入理解跳表及其在 Redis 中的应用
跳表可以达到和红黑树一样的时间复杂度 O(logN),且实现简单,Redis 中的有序集合对象的底层数据结构就使用了跳表。本篇文章从调表的基础概念、节点、初始化、添加方法、搜索方法以及删除方法出发,介绍了调表的完整代码以及调表在redis中的应用。
2023-02-23
学习笔记:TCP 传输控制协议(一)
《TCP/IP详解》是关于网络传输中最经典的一本书,篇幅和文字内容都非常详实,不是短时间能看完的,最近正好也在啃,很多地方茅塞顿开,这里会更新一些自己的理解与认识,希望能有所参考。
2021-09-06
关于 C 语言结构体(struct),你不知道的用法?(初阶篇)
介绍C语言中结构体的一些初阶内容,让大家了解一下结构体是如何去使用的!
2022-09-07
认识区块链,认知区块链——Web3
比特币开启了区块链1.0、智能合约开启区块链2.0,接着无数个新生事物都宣称自己是区块链3.0或4.0或更高,但至今没有看到哪个挑战者站稳了脚跟,但是热度更大的一个词——Web3,接元宇宙之后抗起新的大旗,开启了新的叙事篇章。
2023-01-16
为什么 Stream 使用了 Radix Tree?
Radix Tree这个数据结构的最大特点,是适合保存具有相同前缀的数据,从而实现节省内存空间的目标,以及支持范围查询。
2021-08-10
10|稀疏索引:为什么高并发写不推荐关系数据库?
这节课,我们将要讨论OLAP和OLTP数据库的索引、存储、数据量以及应用的不同场景。
2022-11-14
网页基本代码
网页HTML的基本结构
2022-11-19
Series 的索引和切片
2022-12-29
在 vue 的 v-for 中,key 为什么不能用 index?
在前端中,主要涉及的基本上就是 DOM的相关操作 和 JS,我们都知道 DOM 操作是比较耗时的,那么在我们写前端相关代码的时候,如何减少不必要的 DOM 操作便成了前端优化的重要内容。
2023-01-06
LeetCode:240. 搜索二维矩阵 II,二分查找,详细注释
原题链接:https://leetcode.cn/problems/search-a-2d-matrix-ii/
2023-02-20
React 源码分析 2- 深入理解 fiber
react16 版本之后引入了 fiber,整个架构层面的 调度、协调、diff 算法以及渲染等都与 fiber 密切相关。所以为了更好地讲解后面的内容,需要对 fiber 有个比较清晰的认知。本章将介绍以下内容:
2022-12-08
12|引擎分片:Elasticsearch 如何实现大数据检索?
学完今天的内容,你对大数据分布式的核心实现以及大数据分布式统计服务,都会有更深入的理解。
2022-11-18
什么是大数据:从 GFS 到 Dataflow,12 年大数据生态演化图
要想学好大数据,我们需要先正本清源,弄清楚大数据在技术上到底涵盖了些什么。所以今天这节课,我就从大数据技术的核心理念和历史脉络这两个角度,来带你理解下什么是大数据技术。
2021-09-15
推荐阅读
数据框的索引重建与数据读取
2022-12-29
全链路 Trace 全量存储 - 重造索引
2023-08-14
10|AI 连接外部资料库,让 Llama Index 带你阅读一本书
2023-04-04
数据框的索引
2022-12-29
文心一言 VS 讯飞星火 VS chatgpt (64)-- 算法导论 6.5 3 题
2023-07-21
关于使用 ElascticSearch 的两个小技巧
2023-05-12
Next.js 13.4 版本更新内容~
2023-08-03
电子书

大厂实战PPT下载
换一换 
曾明福 | 财付通 高级开发工程师
杨磊 | 滴普科技 FastData 产品线总裁
吴小伟 | 杭州端点网络科技有限公司 合伙人兼资深技术专家
评论