Lucene最全详解(万字图文教程)

Lucene最全详解(万字图文教程)-mikechen

Lucene定义

Lucene是apache软件基金会发布的一个开放源代码的全文检索引擎工具包,由资深全文检索专家Doug Cutting所撰写,它是一个全文检索引擎。

Lucene的开发语言是Java,也是Java家族中最为出名的一个开源搜索引擎,Solr和ElasticSearch都是基于Lucene封装。

 

Lucene作用

Lucene的目的是为:方便软件开发人员在系统中实现全文检索的功能。

Lucene还提供了完整的创建索引,以及查询索引,以及部分文本分析的引擎。

Lucene是比较成熟的解决方案,有很多的成功案例,经过简单定制优化,可以支持 10亿+ 量级的搜索。

 

Lucene原理

Lucene原理主要是要理解全文检索,会涉及索引创建、索引存储、以及搜索索引。

全文检索原理

Lucene是一个高效的基于Java的全文检索库,所以在了解Lucene之前要费一番工夫了解一下全文检索,这是Lucene原理的核心。

全文检索它的工作原理:就是是计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置。

当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式,这就是全文检索。

全文检索大体分三个过程,索引创建、索引存储、以及搜索索引,下面我分别详解。

Lucene最全详解(万字图文教程)-mikechen

索引创建

将现实世界中所有的结构化和非结构化数据提取信息,这个信息提取的过程,就是索引创建。

1.结构化数据

结构化数据:指具有固定格式,或有限长度的数据,我们一般都是可以通过关系型数据库,比如:mysql,oracle等表的方式存储和搜索。

2.非结构化数据

非结构化数据:指不定长,或无固定格式的数据,比如:word 、HTML这类具有一定规则的非结构化数据。

比如最典型的代表,就是:Google、百度等搜索引擎按照词为单位,把HTML网页存入索引库,然后用户查询词,就会从索引库获取到想要的结果。

这种方式就构成了全文检索的基本思路,这部分从非结构化数据,比如:按照网页为单位中提取出网页标题的关键词,然后重新组织的信息,我们称之索引。

 

倒排索引

上面谈了全文检索技术的原理,下面谈谈全文检索技术的具体实现,绝大多数都基于倒排索引来做,所以要理解Lucene原理,需要掌握倒排索引。

要了解倒排索引,先看一下什么是正排索引。

1.正排索引

举一个生活中的例子:记忆古诗,当别人问我们《静夜思》这首诗的时候,我们很容易就能够背出完整的诗句。

但是如果有人问我们哪一首诗里面,包含有霜这个字的时候,我们就很难想到《静夜思》这首诗了,因为我们的大脑在记忆古诗的时候是建立了一个正排索引。

正排索引就是:输入静夜思,然后出现“窗前明月光,疑是地上霜,举头望明月,低头思故乡”,大脑记忆古诗的这个顺序,这就是正排索引。

 

2.倒排索引

而倒排索引是与这样的数据结构相反的,就是当用户在搜索引擎搜索框中输入关键词的时候。

搜索引擎就会把和关键词有关的页面展现给用户,而这个过程就叫做倒排索引,这个与上面诗句的例子类似。

如下图所示:

Lucene最全详解(万字图文教程)-mikechen

 

倒排索引和正排索引的区别

正排索引是通过文档找单词,既key找value,倒排索引是通过单词找文档,既value找key,这就是两者最大的区别。

倒排索引到此也就讲清楚了,你只要理解了倒排索引这个过程,对搜索引擎就有一个整体的了解了。

 

索引存储

索引创建好后,下一步就是索引存储。

以 Lucene为例,Lucene 的存储结构,如下图所示:

Lucene最全详解(万字图文教程)-mikechen

从大到小是:Index -> Segment -> Doc -> Field -> Term,类比 MySQL 为 Database -> Table -> Record -> Field -> Value。

 

搜索索引

理解了索引的创建过程,最后一步就是搜索索引的查询。

查询索引做了哪些事情?

查询索引主要分为如下3大步骤:

第一步:对查询内容进行词法分析

举个例子,用户输入语句:lucene AND learned NOT hadoop,说明用户想找一个包含lucene和learned,然而不包括hadoop的文档。

这里的AND以及NOT这些分析,这就是词法和语法分析,类似关系数据库oracle、mysql中sql的意义。

 

第二步:搜索索引

这里大致分为如下3步:

首先:在反向索引表中,分别找出包含lucene,learn,hadoop的文档链表。

其次:对包含lucene,learn的链表进行合并操作,得到既包含lucene又包含learn的文档链表。

最后:将此链表与hadoop的文档链表进行差操作,去除包含hadoop的文档,从而得到既包含lucene又包含learn而且不包含hadoop的文档链表。

 

第三步:内容排序

计算权重对返回内容排序,影响一个词(Term)在一篇文档中的重要性主要有两个因素:

Term Frequency (tf):即此Term在此文档中出现了多少次,tf 越大说明越重要。

Document Frequency (df):即有多少文档包含次Term,df 越大说明越不重要。

 

 

Lucene语法使用

Lucene语法主要包含如下几种:

单词查询

Term术语表示文本中的单词,这是搜索单位。

Term由两个元素组成:一个字符串形式的单词文本,另一个文本所在字段的名称。

比如,单词查询:

Query query = new TermQuery(new Term("title", "mike"));

Terrms分为两种,单词查询和词组查询。

比如,词组查询:

Query query = new TermQuery(new Term("title", "mike chen"));

上面的:”mike chen “就是一个词组,词组查询时需要用将词组包括进来,不然会被拆分成两个单词进行查询。

 

通配符查询

可将通常可识别的语法用于多个 (*) 或单个 (?) 字符通配符搜索。

比如:

POST /indexes/hotel-samples-index/docs/search?api-version=2020-06-30
{
    "search": "HotelName:sc*",
    "queryType": "full",
    "select": "HotelName",
    "count": true
}

上面就是HotelName:sc* ,* 匹配sc开头的0个或多个字符。

 

模糊查询

模糊查询,Lucene的模糊查询不同于sql,他是找出与给定条件相近的结果来。

上面输入的是”方财兄“,实际模糊查询匹配,也会去匹配“方才兄”。

范围查询

{}尖括号表示不包含最小值和最大值,可以单独使用。

[]方括号表示包含最小值和最大值,可以单独使用。

比如:

name:{A,C}

搜索名字在A和C之间的, 返回:bone、baby、barry等等。

 

优先级查询

如果单词的匹配度很高,一个文档中,或者一个字段中可以匹配多次,那么可以提升该词的相关度

使用:

使用符号^提高相关度

如下图所示:
Lucene最全详解(万字图文教程)-mikechen

 

逻辑操作

支持多种操作符: AND OR NOT AND: 连接两个搜索条件。

1.搜索同时包含tom和john的文档

tom AND john 或者 tom && john

 

2.搜索包含tom或者john的文档

tom OR john 或者 tom || john

 

3.搜索包含tom,不包含john的文档

tom NOT john 或者 tom && !john

 

4.搜索包含tom的文档

 tom

 

5.搜索不包含tom的文档

-tom

 

陈睿mikechen

10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。

关注「mikechen」公众号,获取更多技术干货!

后台回复面试即可获取《史上最全阿里Java面试题总结》,后台回复架构,即可获取《阿里架构师进阶专题全部合集

评论交流
    说说你的看法