Lucene
简介
编辑Lucene最初是由Doug Cutting所撰写的,是一位资深全文索引/检索专家,曾经是V-Twin搜索引擎的主要开发者,后来在Excite担任高级系统架构设计师,目前从事于一些INTERNET底层架构的研究。他贡献出Lucene的目标是为各种中小型应用程式加入全文检索功能。 Lucene提供了一个简单却强大的应用程式介面,能够做全文索引和搜寻,在java里Lucene是一个成熟的免费开放原始码工具;就其本身而论,Lucene是现在并且是这几年,最受欢迎的免费java资讯检索程式库。人们经常提到资讯检索程式库,就像是搜寻引擎,但是不应该将资讯检索程式库与网搜索引擎相混淆。
如何使用Lucene
编辑Step1:Lucene下载完后将里面的lucene-core-{version}.jar 和lucene-demos-{version}.jar 和 queryparser/lucene-queryparser-{version}.jar 放到
C:\Program Files\Java\jdk1.5.0_11\jre\lib\ext的目錄下
Step2:将上面的3个.jar的档案路径加入到CLASSPATH里完成上面步骤后就可以在Command line下使用Lucene建立Index以及Search。
建立Index:
在Command line下输入java org.apache.lucene.demo.IndexFiles {full-path-to-lucene}/src 即可建立Index。
Search:
在建立完Index之后接著输入java org.apache.lucene.demo.SearchFiles之后会出现Query:字样接著就可以开始Search。
linux环境, lucene-6.3.0例子:
- 取得 lucene-6.3.0.tgz。
- 假设id为boy, cd /home/boy;mkdir lucene
- cd /home/boy; tar zxf lucene-6.3.0.tgz
- export CLASSPATH=/home/boy/lucene-6.3.0/core/lucene-core-6.3.0.jar:/home/boy/lucene-6.3.0/demo/lucene-demo-6.3.0.jar:/home/boy/lucene-6.3.0/queryparser/lucene-queryparser-6.3.0.jar
- cd /home/boy;java org.apache.lucene.demo.IndexFiles -docs /home/boy/lucene-6.3.0 将会读取/home/boy/lucene-6.3.0档案,建立index在目录 /home/boy/index。
- java org.apache.lucene.demo.SearchFiles之后会出现Query:字样接著就可以开始Search。
Lucene分词原理
编辑假若有以下2篇文章:
文章1的内容是:Tom lives in Guangzhou,I live in Guangzhou too.
文章2的内容是:He once lived in Shanghai.
Lucene是用关键词索引和搜寻的,所以我们要先取得上面两篇文章的关键词,步骤如下:
Step1:先找出文章中所有的单字,即分词,因为英文单字是用空格分隔,所以比较好处理,若是中文分词需用到特殊的分词处理。
Step2:把文章中没有意义的单字滤掉,EX:"in","once","too"等等,在中文中就是,"的","是"等等。
Step3:使用者若查询"He"时要能把"he","HE"的文章也找出来,所以所有单字需要统一大小写。
Step4:使用者若查询"live"时,也要将"lives","lived"的文章找出来所以需要把"lives","lived"还原成"live"。
Step5:文章中的标点符号也可以过滤掉。
以上步骤在Lucene中是由Analyzer来完成的。
文章经过处理后:
文章1的所有关键词为:[tom] [live] [guangzhou] [i] [live] [guangzhou]
文章2的所有关键词为:[he] [live] [shanghai]
有了所有的关键词后,我们就可以开始建立倒排索引了。
上面处理过的文章所对应的关系是:"文章编号","文章中所有的关键词"。
若使用一般的索引结构会如下表所示:
文章编号 | 出现的关键词 | 出现次数 |
---|---|---|
1 | guangzhou,i,live,tom | 1,1,1,1 |
2 | he,live,shanghai | 1,1,1 |
从中可以看出一般索引结构是以文章为标准建立索引结构,也就是说他纪录的是一篇文章中所有的关键词出现的情况,EX:文章2中he,live,shanghai均出现一次,然而使用者进行搜寻时,都是输入关键字进行搜寻,若用这种索引结构,在查某依关键字时往往需要遍及所有的索引,当索引量非常大时,效率会成为一个很大的问题。
而倒排索引会把这关系变成:"关键词","出现关键词的所有文章编号"。
所以索引结构如下表所示:
关键词 | 出现关键词的所有文章编号 |
---|---|
guangzhou | 1 |
he | 2 |
i | 1 |
live | 1,2 |
shanghai | 2 |
tom | 1 |
通常只知道以上资讯是不够的,我们还需要知道关键词在文章中出现的次数以及位置。
关键词位置有两种:
符号位置:即纪录该关键词是在文章中第几个符号。
关键词位置:即记录该关键词是在文章中的第几个关键词。(Lucene所用的)
所以上面的资料加入"出现频率"和"出现位置"的讯息后,索引结构就如下表所示:
关键词 | 出现关键词的所有文章编号[出现频率] | 出现位置 |
---|---|---|
guangzhou | 1[2] | 3,6 |
he | 2[1] | 1 |
i | 1[1] | 4 |
live | 1[2],2[1] | 2,5,2 |
shanghai | 2[1] | 3 |
tom | 1[1] | 1 |
以live这行来说明索引结构:live在文章1中出现了2次,在文章2中出现了1次,出现的位置为"2,5,2",也就是说live在文章1中出现了2次,位置分别是"2,5";live在文章2中出现了一次,位置是"2"。
上面就是Lucene索引结构中最核心的部份。我们可以看出关键词是依照符号顺序排列的,因此Lucene可以利用二元搜寻法来定位关键词。
实际上Lucene将上面的"关键词","文章编号[出现频率]","出现位置"分成(辞典文件)Term Dictionary,(频率文件)frequencies,(位置文件)positions保存。
其中Term Dictionary不只存有每个关键词,还保留了frequencies和positions的指针,透过指针可以找到该关键词的频率讯息和位置讯息。
Lucene也使用了field的概念,field是用于表达讯息的所在位置(EX:标题中,文章中,url中),在建立索引时field的讯息也被记录在Term Dictionary中,每一个关键词都有一个field讯息(因为每一个关键词一定属于一个或多个)。
下面我们将说明为什么要建立索引(Index):
假设我们查询"live",Lucene会用二元搜寻法对Term Dictionary做关键词的寻找,找到该关键词后,透过指向frequencies的指针读出所有的文章编号,然后将找到的文章输出给使用者。Term Dictionary通常都很小,所以整个过程的时间是毫秒级的。