1、理论基础

1.1、顺序扫描法

所谓顺序扫描,例如要找内容包含一个字符串的文件,就是一个文档一个文档的看,对于每一个文档, 从头看到尾,如果此文档包含此字符串,则此文档为我们要找的文件,接着看下一个文件,直到扫描完所有的文件。

优点:

  • 查询准确率高

缺点:

  • 查询速度会随着查询数据量的增大,
  • 越来越慢

使用场景:

  • 数据库中的like关键字模糊查询
  • 文本编辑器的Ctrl + F 查询功能

    1.2、倒排索引

先举一个栗子:
例如我们使用新华字典查询汉字,新华字典有偏旁部首的目录(索引),我们查字首先查这个目录,找 到这个目录中对应的偏旁部首,就可以通过这个目录中的偏旁部首找到这个字所在的位置(文档)。

Lucene会对文档建立倒排索引

  • 提取资源中关键信息, 建立索引 (目录)
  • 搜索时,根据关键字(目录),找到资源的位置

算法描述:
查询前会先将查询的内容提取出来组成文档(正文), 对文档进行切分词组成索引(目录), 索引和文档有关联 关系, 查询的时候先查询索引, 通过索引找文档的这个过程叫做全文检索。

优点:

  • 查询准确率高
  • 查询速度快, 并且不会因为查询内容量的增加, 而使查询速度逐渐变慢

缺点:

  • 索引文件会占用额外的磁盘空间, 也就是占用磁盘量会增大。

使用场景:

  • 海量数据查询

为什么倒排索引比顺序扫描快?
理解 : 因为索引可以去掉重复的词, 汉语常用的字和词大概等于, 字典加词典, 常用的英文在牛津词典也
有收录.如果用计算机的速度查询, 字典+词典+牛津词典这些内容是非常快的. 但是用这些字典, 词典组成
的文章却是千千万万不计其数. 索引的大小最多也就是字典+词典. 所以通过查询索引, 再通过索引和文档
的关联关系找到文档速度比较快. 顺序扫描法则是直接去逐个查询那些不计其数的文章就算是计算的速
度也会很慢.

1.1、全文检索

计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数 和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索 方式

应用场景 :

  • 站内搜索 (baidu贴吧、论坛、 京东、 taobao)
  • 垂直领域的搜索 (818工作网)
  • 专业搜索引擎公司 (google、baidu)

2、什么是Lucene

Lucene是apache软件基金会 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎

  1. Lucene是一套用于全文检索和搜寻的开源程式库,由Apache软件基金会支持和提供。Lucene提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻。在Java开发环境里Lucene是一个成熟的免费开源工具。就其本身而言,Lucene是当前以及最近几年最受欢迎的免费Java信息检索程序库。

目前已经有很多应用程序的搜索功能是基于 Lucene 的,比如 Eclipse 的帮助系统的搜索功能。Lucene 能够为文本类型的数据建立索引,所以你只要能把你要索引的数据格式转化的文本的,Lucene 就能对 你的文档进行索引和搜索。比如你要对一些 HTML 文档,PDF 文档进行索引的话你就首先需要把
HTML 文档和 PDF 文档转化成文本格式的,然后将转化后的内容交给 Lucene 进行索引,然后把创建好
的索引文件保存到磁盘或者内存中,最后根据用户输入的查询条件在索引文件上进行查询。不指定要索
引的文档的格式也使 Lucene 能够几乎适用于所有的搜索应用程序。

  • Lucene是一套用于全文检索和搜寻的开源程式库,由Apache软件基金会支持和提供
  • Lucene提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻, 在Java开发环境里

Lucene是一个成熟的免费开放源代码工具

  • Lucene并不是现成的搜索引擎产品,但可以用来制作搜索引擎产品


3、创建索引流程

image.png
image.png

3.1、原始内容

原始内容是指要索引和搜索的内容。
原始内容包括互联网上的网页、数据库中的数据、磁盘上的文件等。

3.2、获取文档

从互联网上、数据库、文件系统中等获取需要搜索的原始信息,这个过程就是信息采集,采集数据的目 的是为了对原始内容进行索引。

采集数据分类:
1、对于互联网上网页,可以使用工具将网页抓取到本地生成html文件。
2、数据库中的数据,可以直接连接数据库读取表中的数据。
3、文件系统中的某个文件,可以通过I/O操作读取文件的内容。
在Internet上采集信息的软件通常称为爬虫或蜘蛛,也称为网络机器人,爬虫访问互联网上的每一个网 页,将获取到的网页内容存储起来。

3.3、创建文档

获取原始内容的目的是为了索引,在索引前需要将原始内容创建成文档(Document),文档中包括一 个一个的域(Field),域中存储内容。

这里我们可以将磁盘上的一个文件当成一个document,Document中包括一些Field,如下图:
image.png
注意:每个Document可以有多个Field,不同的Document可以有不同的Field,同一个Document可以
有相同的Field(域名和域值都相同)

3.4、分析文档

将原始内容创建为包含域(Field)的文档(document),需要再对域中的内容进行分析,分析成为一 个一个的单词。

比如下边的文档经过分析如下:

原文档内容:
vivo X23 8GB+128GB 幻夜蓝 全网通4G手机
华为 HUAWEI 麦芒7 6G+64G 亮黑色 全网通4G手机

分析后得到的词:
vivo, x23, 8GB, 128GB, 幻夜, 幻夜蓝, 全网, 全网通, 网通, 4G, 手机, 华为, HUAWEI, 麦芒7。。。。

3.5、索引文档

对所有文档分析得出的语汇单元进行索引,索引的目的是为了搜索,最终要实现只搜索被索引的语汇单 元从而找到Document(文档)。

创建索引是对语汇单元索引,通过词语找文档,这种索引的结构叫倒排索引结构。

倒排索引结构是根据内容(词汇)找文档,如下图:
image.png
倒排索引结构也叫反向索引结构,包括索引和文档两部分,索引即词汇表,它的规模较小,而文档集合 较大。
image.png

4、Lucene优化

4.1、解决大量磁盘IO

confifig.setMaxBufffferedDocs(100000); 控制写入一个新的segment前内存中保存的document的
数目,设置较大的数目可以加快建索引速度。

数值越大索引速度越快, 但是会消耗更多的内存
indexWriter.forceMerge(文档数量); 设置N个文档合并为一个段

数值越大索引速度越快, 搜索速度越慢; 值越小索引速度越慢, 搜索速度越快
更高的值意味着索引期间更低的段合并开销,但同时也意味着更慢的搜索速度,因为此时的索引通
常会包含更多的段。如果该值设置的过高,能获得更高的索引性能。但若在最后进行索引优化,那
么较低的值会带来更快的搜索速度,因为在索引操作期间程序会利用并发机制完成段合并操作。故
建议对程序分别进行高低多种值的测试,利用计算机的实际性能来告诉你最优值。

4.2、选择合适的分词器

不同的分词器分词效果不同, 所用时间也不同
虽然StandardAnalyzer切分词速度快过IKAnalyzer, 但是由于StandardAnalyzer对中文支持不好, 所
以为了追求好的分词效果, 为了追求查询时的准确率, 也只能用IKAnalyzer分词器, IKAnalyzer支持停
用词典和扩展词典, 可以通过调整两个词典中的内容, 来提升查询匹配的精度

4.3、选择合适的位置存放索引库

image.png

4.4、搜索api的选择

  1. 尽量使用TermQuery代替QueryParser
    2. 尽量避免大范围的日期查询

    5、使用注意事项

  • 关键词区分大小写 OR AND TO等关键词是区分大小写的,lucene只认大写的,小写的当做普通单

词。

  • 读写互斥性 同一时刻只能有一个对索引的写操作,在写的同时可以进行搜索
  • 文件锁 在写索引的过程中强行退出将在tmp目录留下一个lock文件,使以后的写操作无法进行,

可以将其手工删除

  • 时间格式 lucene只支持一种时间格式yyMMddHHmmss,所以你传一个yy-MM-dd HH:mm:ss的

时间给lucene它是不会当作时间来处理的

  • 设置boost 有些时候在搜索时某个字段的权重需要大一些,例如你可能认为标题中出现关键词的文

章比正文中出现关键词的文章更有价值,你可以把标题的boost设置的更大,那么搜索结果会优先 显示标题中出现关键词的文章