elasticsearchElasticSearch&Lucene我爱编程

Lucene基础篇-基本概念

2018-05-15  本文已影响36人  留两口

基本概念

Token

Token在Lucene与在自然语言处理(NLP,Natural-language processing)中的概念相同,表示“词元”。词元即自然语言中的基本单位:在中文表现为一个独立的字或词,在英文中表现为一个单词。

将句子处理成Token的过程,称为分词,而完成分词工作的组件称为分词器(Analyzer)。分词器的选择根据语言、场景而不同:用户可以选择Lucene中内置的分词器,也可以自定义实现分词器。

总的来说,中文分词要比英文分词复杂。本篇介绍英文分词,有关中文分词的内容,后续单独介绍。

在Lucene中,分词通常包含以下步骤:

分词流程示例
  1. 拆分单词(Split):像英文这种带有自然分隔(空格、标点符号)的语言,可以简单地按照分隔符进行拆分。
  2. 排除停用词(Stop Words):自然语言中含有大量没有实际含义的功能词,在自然语言处理中,遇到这类词,就会停止处理,所以称这些功能词为停用词。停用词通常表现为冠词(eg. a、the)、介词(eg. on、in)、副词(eg. how、when)或连词(eg. and)。在分词时排除停用词,既减少了索引量,又提高了检索效率和效果。关于停用词的段子:从品牌辨识度、图形独特性和美感角度,如何评价中国移动新品牌「and 和」的名称及其 logo 设计? - 傅渥成的回答 - 知乎
  3. 词干提取( Stemming):英文中含有名词复数、第三人称单数、过去时、进行时等一系列衍生词,一般而言,我们真正关心的是它们的词根。抽取单词词根的过程称为词干提取。主流的Stemming算法有Porter stemming algorithmLovins stemming algorithmLancaster(Paice/Husk) stemming algorithm。Lucene 使用了 Snowball 语言编写的词干提取算法,并将其封装在了lucene-analyzers-common包中。
  4. 单词小写化(Lower Case):针对搜索词大小写不敏感的情况,在分词时,会把单词统一转化为小写形式。

Field

Field(域)可以类比关系型数据库中的字段的概念。Field包含三个部分:名称、类型、值。

常用的Field有数值型、字符串型、文本型。

Field继承关系

下面是常用的Field与关系型数据库字段的对照关系:

字段类型 关系型数据库(以MySQL为例) Lucene 说明
数值型 int、bigint、double IntPoint、LongPoint、DoublePoint -
字符串型 varchar StringField StringField中的值不会分词
文本型 text TextField TextField中的值会做分词处理
日期型 date、timestamp、datetime - Lucene没有提供日期型Field,但是可以根据需要将日期转为数值型或字符串型Field

Document

Document(文档)是Field的集合。Document可以类比为关系型数据库中的记录,不同的是,Document并非结构化的,并没有schema的约束:

举个例子:

​ 一个Document可以描述一个人的信息,可能包含姓名、年龄等字段;

​ 另外一个Document可以描述一本书的信息,可能包含书名、作者等字段,并且可以有多个名为作者的字段。

Directory

Directory是Document的集合,描述了Lucene索引的存放位置,可类比关系型数据库中的数据库:

数据库有MySQL、Oracle之分,Directory也有不同的实现:

Directory核心实现类
Directory子类 描述
SimpleFSDirectory 最简单的Directory子类,使用java.io.* API将文件存入文件系统。不能很好支持多线程操作
NIOFSDirectory 使用java.nio.* API将文件保存至文件系统。能很好支持除Windows之外的多线程操作,原因是Sun的JRE在Windows平台上长期存在问题
MMapDirectory 使用内存映射I/O进行文件访问。对于64位JRE来说是一个很好的选择,对于32位JRE并且索引尺寸相对较小时也可以使用该类
RAMDirectory 将所有文件都存入RAM
FIleSwitchDirectory 使用两个文件目录,根据文件扩展名在两个目录之间切换使用

表格中内容摘自《Lucene In Action》一书

如果选择将索引保存在文件系统中,可以显式指定使用哪个Directory子类,也可以使用Lucene提供的工厂方法,让Lucene为你做最优选择:

org.apache.lucene.store.FSDirectory#open(java.nio.file.Path)

Query

Query类似关系型数据库中的SQL语句。与关系型数据库类似,Lucene提供了以下的基本查询:

查询类型 关系型数据库 Lucene
精确查询 xxx = ? TermQuery
范围查询 xxx BETWEEN? AND ? IntRange、LongRange、DoubleRange
模糊查询 xxx LIKE '%?%' PrefixQuery、RegexpQuery
组合查询 (...) AND (...) OR (...) BooleanQuery

倒排索引

倒排索引(Inverted Index,也叫反向索引)是相较正排索引(Forward Index,也叫正向索引)而言的。

简单来说,正排索引描述的是每个文档包含哪些词;倒排索引描述的是某个词出现在哪些文档中。

假设有如下编号的文档:

1. the fox jumps over the dog
2. god save dog

建正排索引如下:

文档编号 包含单词
1 {the, fox, jumps, over, dog}
2 {god, save, dog}

建倒排索引如下:

单词 包含该单词的文档
the {1}
fox {1}
... ...
dog {1, 2}

不难发现,如果要搜索哪些文档包含给定的单词,正排索引需要O(N)的时间,而倒排索引需要O(1)的时间。

Lucene中的倒排索引要比这复杂得多,不仅存储包含某单词的文档编号,而且会存储该单词在各文档中的出现频率以及位置信息等。

以上是Lucene的基本概念,下一篇开始,会介绍Lucene中的CRUD操作。

上一篇下一篇

猜你喜欢

热点阅读