Lucene定义
Lucene是apache软件基金会发布的一个开放源代码的全文检索引擎工具包,由资深全文检索专家Doug Cutting所撰写,它是一个全文检索引擎。
Lucene的开发语言是Java,也是Java家族中最为出名的一个开源搜索引擎,Solr和ElasticSearch都是基于Lucene封装。
Lucene作用
Lucene的目的是为:方便软件开发人员在系统中实现全文检索的功能。
Lucene还提供了完整的创建索引,以及查询索引,以及部分文本分析的引擎。
Lucene是比较成熟的解决方案,有很多的成功案例,经过简单定制优化,可以支持 10亿+ 量级的搜索。
Lucene原理
Lucene原理主要是要理解全文检索,会涉及索引创建、索引存储、以及搜索索引。
全文检索原理
Lucene是一个高效的基于Java的全文检索库,所以在了解Lucene之前要费一番工夫了解一下全文检索,这是Lucene原理的核心。
全文检索它的工作原理:就是是计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置。
当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式,这就是全文检索。
全文检索大体分三个过程,索引创建、索引存储、以及搜索索引,下面我分别详解。
索引创建
将现实世界中所有的结构化和非结构化数据提取信息,这个信息提取的过程,就是索引创建。
1.结构化数据
结构化数据:指具有固定格式,或有限长度的数据,我们一般都是可以通过关系型数据库,比如:mysql,oracle等表的方式存储和搜索。
2.非结构化数据
非结构化数据:指不定长,或无固定格式的数据,比如:word 、HTML这类具有一定规则的非结构化数据。
比如最典型的代表,就是:Google、百度等搜索引擎按照词为单位,把HTML网页存入索引库,然后用户查询词,就会从索引库获取到想要的结果。
这种方式就构成了全文检索的基本思路,这部分从非结构化数据,比如:按照网页为单位中提取出网页标题的关键词,然后重新组织的信息,我们称之索引。
倒排索引
上面谈了全文检索技术的原理,下面谈谈全文检索技术的具体实现,绝大多数都基于倒排索引来做,所以要理解Lucene原理,需要掌握倒排索引。
要了解倒排索引,先看一下什么是正排索引。
1.正排索引
举一个生活中的例子:记忆古诗,当别人问我们《静夜思》这首诗的时候,我们很容易就能够背出完整的诗句。
但是如果有人问我们哪一首诗里面,包含有霜这个字的时候,我们就很难想到《静夜思》这首诗了,因为我们的大脑在记忆古诗的时候是建立了一个正排索引。
正排索引就是:输入静夜思,然后出现“窗前明月光,疑是地上霜,举头望明月,低头思故乡”,大脑记忆古诗的这个顺序,这就是正排索引。
2.倒排索引
而倒排索引是与这样的数据结构相反的,就是当用户在搜索引擎搜索框中输入关键词的时候。
搜索引擎就会把和关键词有关的页面展现给用户,而这个过程就叫做倒排索引,这个与上面诗句的例子类似。
如下图所示:
倒排索引和正排索引的区别
正排索引是通过文档找单词,既key找value,倒排索引是通过单词找文档,既value找key,这就是两者最大的区别。
倒排索引到此也就讲清楚了,你只要理解了倒排索引这个过程,对搜索引擎就有一个整体的了解了。
索引存储
索引创建好后,下一步就是索引存储。
以 Lucene为例,Lucene 的存储结构,如下图所示:
从大到小是: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等等。
优先级查询
如果单词的匹配度很高,一个文档中,或者一个字段中可以匹配多次,那么可以提升该词的相关度
使用:
使用符号^提高相关度
如下图所示:
逻辑操作
支持多种操作符: 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面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》