vlambda博客
学习文章列表

快速上手搜索引擎的秘密武器——Lucene

这篇文章介绍下这个 Lucene,下篇写写 ElasticSearch , 然后再继续填 Spring 的坑 🕳

内容的话就很基础啦🐖,希望能帮你快速入门,了解下它

目录

image-20210930071825137

为啥要介绍这个 Lucene 呢?毕竟它是搜索引擎核心中的核心

其实是因为我想体验下这个工具包,试着感受下 ElasticSearch 为啥要封装它?以及他们之间的联系~ 等🐖

Lucene

Lucene 是一个开源的,全文索引工具包。有 索引,搜索,分词 等功能

ElasticSearch 和 Apache Solr 的核心。

在 MySQL 中,Innodb 和 MyISAM 的索引结构都是 B+树, 而到了 Lucene , 就不得不说下这个倒排索引了。

倒排索引

这个就是通过  value ——> Key ,感觉有点像 MySQL 的回表操作🐖,但是这里还有 分词,文档 等概念。

比如我们平时在 百度,Google ,电商平台等中进行搜索时,就是通过这个 关键字 找到相应的 文档 内容出来

概念

下面会介绍下这些概念 👇

快速上手搜索引擎的秘密武器——Lucene
概念一览

他们之间的关系就用这个来表示啦,这个也是本文的重点🐖

快速上手搜索引擎的秘密武器——Lucene
概念图

下面开始一一介绍啦😄

文档

对应 Document 对象 👇

文档 是 Lucene 内部的数据结构,索引文档时,会按照一定规则去创建索引,生成倒排索引文件。

查询时就直接搜索到对应的索引文件,获取数据,效率非常高!

它是搜索和索引的单位,也是字段的集合。

快速上手搜索引擎的秘密武器——Lucene
image-20210929070420233

字段

对应 Field 对象 👇 ,由三部分组成 :name,type,value

  • name : 字段域名, 可以看作我们创建的 Model 的属性名称,如 name,age,id 等等,在同个索引库中是唯一的
  • value  :   字段值, 存储文档的部分内容,如 name:Java4ye 这个 Field 中的值   Java4ye
  • type   :   字段类型,如 是否分词,索引,存储 等
快速上手搜索引擎的秘密武器——Lucene
image-20210929070834194

词汇

对应 Term 对象 👇 ,由两部分组成 :name,value

  • name : Field 的名称 ,即 字段域名
  • value  :   Field 中文档的部分内容 ,即 字段值
快速上手搜索引擎的秘密武器——Lucene
image-20210929073043617

如果还不清楚,那么再看看下面这里你就懂啦~

分词

这个是超级核心! 🐖

分词的目的是为了索引,索引的目的是为了搜索,就像查字典一样🐖

分词的过程是先分词,再过滤(过滤掉标点符号,停用,重复的词,大写转成小写等)

比如这个标准分词器 :StandardAnalyzer 👇

通过注释可以发现它会进行 停用词,大写转成小写 的过滤操作。

快速上手搜索引擎的秘密武器——Lucene
image-20210929080734487

中文分词器推荐 IK-Analyzer

小结

那么到了这里,咱们再把上面的知识点串一串~ 😄

通过咱们这个分词器,会对字段域中的 value 进行分词,当然你也可以根据需求选择不分词。

不分词就一个 Term ,分词后会产生很多 Term,Term 的 name 就是这个 字段域的名称, Value 就是分出来的词。

比如 对 desc:nice to meet you 的字段域进行过分词。会出现这四个单词:nice,to,meet,you

快速上手搜索引擎的秘密武器——Lucene
Field 和 Term 的关系

索引库

差点漏了这个~

可以看到里面有 段的概念 Segment 和 锁🔒 等

快速上手搜索引擎的秘密武器——Lucene
image-20210930080914187

把整个文件夹看成一个 Index,Segment  就是里面的 sub-index。

当创建索引时,不是立刻就刷到磁盘的,需要先写入缓冲区,然后等满了,或者关闭了,手动 flush 等操作才一起写入磁盘,这也是它为什么是 近实时而非实时查询 的原因 🐖

查询时其实就是在 Segment  中查找,需要对多个 Segment 进行合并,搜索,找到相应的 docID ,再去存放数据的文件中获取并返回。

Luke

https://github.com/DmitryKey/luke

这里用这个 Luke 工具演示下 👇

快速上手搜索引擎的秘密武器——Lucene
Luke工具

可以看到 desc 字段域分词后有四个 Term 。


上面介绍完了这些概念,这里就来开始实践啦,将这些概念串联起来,代码同样可以在 Github  上获取 👇

https://github.com/Java4ye/springboot-demo-4ye

全文检索流程

快速上手搜索引擎的秘密武器——Lucene
图片来自网络

这里就两个操作👉  创建索引 和 查询索引 ,操作步骤写代码里啦,就不多说了🐖

创建索引

快速上手搜索引擎的秘密武器——Lucene
image-20210929224345327

查询索引

快速上手搜索引擎的秘密武器——Lucene
image-20210930072539002

奇怪的收获

由于项目中引入了 ElasticSearch , 它的底层核心又是 Lucene ,所以这里我没有再去引入 Lucene , 而是直接使用,结果却成了踩坑的开始🐖

这里可以看到 Lucene 是8.5.1 版本的,这样 Luke 工具是运行不了的 ,会报错,但是 Lucene8.0 版本可以运行,所以得重新引包。

快速上手搜索引擎的秘密武器——Lucene
image-20210928210532558

为啥报错呢?

可以看到作者在说这个工具不维护了🐖

Lucene 也早就捐献给 Apache 了

快速上手搜索引擎的秘密武器——Lucene
image-20210929231213122

同时我还发现了  Luke 工具使用到这个 JavaSPI 机制。

快速上手搜索引擎的秘密武器——Lucene
image-20210929230604020

还有 Lucene 底层关键字的数据结构是 跳跃表 ( Redis 也用到了), FST 状态机。

FST, 全称Finite State Transducer, 中文翻译: 有限状态转换器或有限状态传感器。FST 最重要的功能是可以实现 Key 到 Value 的映射,相当于 HashMap<Key,Value>。FST 的内存消耗要比HashMap 少很多,但 FST 的查询速度比 HashMap 要慢。FST 在 Lucene 中被大量使用,例如:倒排索引的存储,同义词词典的存储,搜索关键字建议等

跳跃表 不支持模糊查询  ,FST 支持模糊查询

搜索过程

大概就是这样,通过这个词,去找到对应的文档id,再获取文档出来,依据权重啥的排序。

image-20210930075225873

词典数据结构有这么多种👇

图片来自网络

最后

本文就分享到这里啦🐖

往细了看,可以发现这里涉及到很多 IO原理,以及底层数据结构的知识,编码上目前就粗略认识到这个 JavaSPI 的使用。

快去敲下代码,了解这些概念吧,这样是不是也能有个基础版的搜索引擎了 哈哈😝

👉 https://github.com/Java4ye/springboot-demo-4ye

我是4ye 咱们下期应该……很快再见!! 😆