Lucene查询语法

1.Lucene语法简介

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

那么先来说一说什么是全文检索

我们应用中的数据总体分为两种:结构化数据非结构化数据

(1) 结构化数据:指具有固定格式或有限长度的数据,如数据库,元数据等。

对于结构化数据查询,使用数据库搜索,数据库中的搜索很容易实现,通常都是使用sql语句进行查询,而且能很快的得到查询结果。

为什么数据库搜索很容易?因为数据库中的数据存储是有规律的,有行有列而且数据格式、数据长度都是固定的。

(2) 非结构化数据:指不定长或无固定格式的数据,如邮件,word文档等磁盘上的文件

非结构化数据查询方法包括以下两种方法:

<1>顺序扫描法(Serial Scanning)

所谓顺序扫描,比如要找内容包含某一个字符串的文件,就是一个文档一个文档的看,对于每一个文档,从头看到尾,如果此文档包含此字符串,则此文档为我们要找的文件,接着看下一个文件,直到扫描完所有的文件。如利用windows的搜索也可以搜索文件内容,只是相当的慢

<2>全文检索(Full-text Search)

将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引

例如:字典。字典的拼音表和部首检字表就相当于字典的索引,对每一个字的解释是非结构化的,如果字典没有音节表和部首检字表,在茫茫辞海中找一个字只能顺序扫描。然而字的某些信息可以提取出来进行结构化处理,比如读音,就比较结构化,分声母和韵母,分别只有几种可以一一列举,于是将读音拿出来按一定的顺序排列,每一项读音都指向此字的详细解释的页数。我们搜索时按结构化的拼音搜到读音,然后按其指向的页数,便可找到我们的非结构化数据——也即对字的解释。

这种先建立索引,再对索引进行搜索的过程就叫全文检索(Full-text Search)

2.Lucene实现全文检索流程

全文检索流程

上图是Lucene实现全文检索的大致流程,也可参考:全文检索流程

1、绿色部分表示索引过程,对要搜索的原始内容进行索引构建一个索引库,索引过程包括:

        确定原始内容即要搜索的内容→采集文档→创建文档→分析文档→索引文档

2、红色部分表示搜索过程,从索引库中搜索内容,搜索过程包括:

        用户通过搜索界面→创建查询→执行搜索,从索引库搜索→渲染搜索结果

3.Lucene查询语法

可参考官网:http://lucene.apache.org/core/3_0_3/queryparsersyntax.html

(1) (Terms)

一个查询将分解为若干Term以及操作符,有两种Term,其一是单一Term,其二为短语。单一Term是经过分析器分词后的最小单元,就是一个简单的词,例如“Test”和“Hello”。短语则是一组被双引号括起来的一组词,例如:“Hello dolly”,多个Term可以通过布尔操作合并在一个更加复杂的查询器中。

注意:一般来说,创建索引的分析器和查询的分析器最好保持一致(当然也有特殊情况,比如单字索引,分词组合查询),所以选择一个不会干扰查询词的分析器是很重要的。

(2) 域(Fields)

Lucene支持多字段数据,当你在查询的时候你可以指定一个字段查询,也可以使用默认的字段。你可以使用

字段名:查询词

来指定字段名搜索。举个栗子,让我们假定Lucene的索引中含有两个字段,Title字段和Text字段,其中Text字段是默认字段,当你想找到一篇文档其中标题包含“The Right Way”同时文本中包含“go”,你可以输入:

title:"The Right Way" AND text:go 

或者:

title:"The Right Way" AND go 

如果字段是默认字段的话,在查询语法中可以不需要显式指定。注意,使用默认字段有可能会造成如下的结果:

title:Do it right 

:仅对紧跟其后的查询词起作用,以上查询将查找标题中含有“Do”,Text字段字段中含有“it”和“right”的文档,因为Text是默认字段,所以如果想要查找Title中完整包含的需用引号引起来。

(3) 通配符查询(Wildcard)

Lucene支持单个或者多个字符的通配符查询,匹配单一字符使用符号“?”,匹配多个字符使用符号“*”。

“?”通配符将查找所有满足通过一个字符替换后符合条件的文档。比如:搜索“test”和“text”你可以使用:

te?t 

“*”通配符将查询0个或者多个字符替换后符合条件的。举例来说,查询test,tests或者tester,你可以使用一下字符串来搜索:

test*

当然,你也可以将“*”放在字符的中间

te*t 

注意:你不能将“*”和“?”放在第一个字符来查询。(Lucene应该是出于性能考虑,所以不支持该功能)

(4) 模糊查询(Fuzzy)

模糊查询的算法是基于编辑距离算法(Levenshtein Distance)的,也即当两个词的差别小于某个比例的时候,就算匹配,如roam~0.8,即表示差别小于0.2,相似度大于0.8才算匹配。可以使用波浪符号“~”放在查询词的后面,比如搜索一个与“roam”拼写相近的词可以使用:

roam~ 

该查询将寻找类似“foam”和“roams”等的词语。也可以说是相似度查询。

(5) 邻近查询(Proximity)

Lucene支持指定距离查询,你可以使用波浪号“~”加数字在查询词后。举例来说搜索“apache”和“jakarta”距离10个字符以内,你可以使用如下语法:

"jakarta apache"~10 

通过这个语法支持,我们可以单字索引,分词查询,分词完后,满足每个词的单字必须间距为1。这样可以保证100%的召回率,但是在索引方面将造成索引臃肿,同时查询速度也将在某程度上降低,一般来说,在150W文章数据到200W数据的时候性能将会明显的降低。

在词组后面跟随~10,表示词组中的多个词之间的距离之和不超过10,则满足查询。

所谓词之间的距离,即查询词组中词为满足和目标词组相同的最小移动次数。

(6) 范围查询(Range)

范围查询允许你指定某个字段最大值和最小值,查询在二者之间的所有文档。范围查询可以包含或者不包含最大值和最小值,排序是按照字典顺序来排序的。

date:[20020101 TO 20030101] 

这个将查找满足date字段在大于等于20020101,小于等于20030101范围的所有文档,注意:范围查询并不是为日期字段专设的,你也可以对非日期字段进行范围查询。

title:{Aida TO Carmen} 

这个将查找所有标题在Aida和Carmen之间但不包含Aida和Carmen的文档。包含最大值和最小值的查询使用方括号,排除则使用花括号。

(7) 优先级

增加一个查询词的权重(Boosting a Term)

Lucene支持给不同的查询词设置不同的权重。设置权重使用“^”符号,将“^”放于查询词的尾部,同时跟上权重值,权重因子越大,该词越重要。设置权重允许你通过给不同的查询词设置不同的权重来影响文档的相关性,假如你在搜索:

jakarta apache 

如果你认为“jakarta”在查询时中更加重要,你可以使用如下语法:

jakarta^4 apache 

这将使含有Jakarta的文档具有更高的相关性,同样你也可以给短语设置权重如下:

"jakarta apache"^4 "jakarta lucene" 

在默认情况下,权重因子为1。如果大于1,则说明此查询词更重要;如果小于1,则说明此查询词更不重要。

(8) 布尔操作符(Boolean operators)

布尔操作符可以将多个Term合并为一个复杂的逻辑查询。Lucene支持AND,+,OR,NOT, -作为操作符号。注意,所有的符号必须为大写

AND 

AND操作符规定必须所有的Term都出现才能满足查询条件,这跟逻辑符号&&意思相似。如果我们要搜索一个文档中同时含有“jakarta apache”和“jakarta lucene”,我们可以使用如下语法:

"jakarta apache" AND "jakarta lucene" 

+

+操作符规定在其后的Term必须出现在文档中,也就是查询词中的MUST属性。举个例子来说,当我们要查询一个文档必须包含“jakarta”,同时可以包含也可以不包含“lucene”时,我们可以使用如下语法:

+jakarta apache 

OR 

OR操作符默认的连接操作符。这意味着,当没有给多个Term显式指定操作符时,将使用OR,只要其中一个Term含有,则可以查询出文档,这跟逻辑符号 || 的意思相似。假设我们查询一个文档含有“jakarta apache”或者“jakarta”时,我们可以使用如下语法:

"jakarta apache" jakarta 

或者

"jakarta apache" OR jakarta 

NOT 

NOT操作符规定查询的文档必须不包含NOT之后的Term,这跟逻辑符号中的!相似。当我们要搜索一篇文档中必须含有“jakarta apache”同时不能含有“Jakarta lucene”时,我们可以使用如下查询;

"jakarta apache" NOT "jakarta lucene" 

注意:NOT操作符不能使用在单独Term中,举例来说,以下查询将返回无结果:

NOT "jakarta apache" 

-操作符排除了包含其后Term的文档,跟NOT有点类似,假设我们要搜索“Jakarta apache”但不包含“Jakarta lucene”时,我们使用如下语法:

"jakarta apache" -"jakarta lucene" 

(9) 组合(Grouping) 

Lucene支持使用圆括号来将查询表达式分组,这将在控制布尔控制查询中非常有用。举例来说:当搜索必须含有“website”,另外必须含有“jakarta”和“apache”之一,我们可以用如下语法:

(jakarta OR apache) AND website 

这种语法对消除歧义,确保查询表达式的正确性具有很大的意义。

域组合(Field Grouping) 

Lucene支持对某字段用圆括号来进行分组,当我们要查询标题中含有“return”和“pink ranther”时,我们可以使用如下语法:

title:(+return +"pink panther") 

(10) 转义特殊字符(Escaping Special Characters)

Lucene支持转义查询中的特殊字符,以下是Lucene的特殊字符清单:

+ - && || ! ( ) { } [ ] ^ " ~ * ? : \

转义特殊字符我们可以使用反斜杠符号“\”放于字符之前。比如我们要搜索(1+1):2,我们可以使用如下语法:

\(1\+1\)\:2

推荐阅读更多精彩内容