概览
Lucene 除了提供 API 方便开发者创建查询请求,还通过一个查询解析器(词法分析器,使用 JavaCC 将字符串翻译成 Lucene 查询语句)提供一种功能丰富的查询语言。
一般来说,查询解析器支持的语法在不同发布版本之间可能会有变化。本文档描述的是当前版本的语法。如果你正在使用一个不同版本的 Lucene,请参考该版本自带的 docs/queryparsersyntax.html
文档。
在选择使用这个查询解析器之前,请考虑以下 3 点:
- 如果你准备以编程的方式生成一个查询字符串,然后使用查询解析器来解析它。那么,你应该认真考虑一下是否应该直接使用查询 API 来构建查询。换句话说,查询解析器专门用于人类输入的文本,而不是程序生成的文本。
- 没有被识别为token的域最好直接添加到查询中,而不是通过查询解析器来解析。如果一个域的值是通过应用自动生成的,那么应该为这个域自动生成查询子句。查询解析器所使用的分析器是专门用于将人类输入的文本转换成词(terms)的。由程序生成的值,如日期、关键字等等,也应该由程序添加到查询中。
- 从查询形式来看,如果域的值是普通文本,则应该使用查询解析器。所有其它值类型,比如:日期范围、关键字等等,最好通过查询 API 直接添加。如果一个域的值仅限于一个有限的集合(可以通过一个下拉菜单指定),则不应该添加到查询字符串(后续会被解析)中,而是应该作为一个 TermQuery 子句添加到查询中。
词(Terms)
一个查询语句可以拆解成 词(terms) 和 操作符(operators)。词又分为两种:单个词(single Terms)和短语(Phrases)。
单个词是指 ”test“ 或 ”Hello“ 这类单词。
短语是指以双引号包围起来的一组单词,比如:”hello dolly“。
多个词(Multiple terms)可以使用布尔操作符组合在一起,实现一个更加复杂的查询(如下文所示)。
备注:用于创建索引的解析器也会用于解析查询字符串中的词和短语。因此,选择合适的解析器很重要,否则解析器可能会被查询字符串中的词干扰。
域(Fields)
Lucene 支持分多个字段/域的数据。搜索时,可以指定一个域,也可以使用默认域。域的名称以及默认域与具体实现相关。
输入域的名称,后跟一个冒号(:),再跟目标搜索词,即可对任意一个域进行搜索。
举例来说,假设一个 Lucene 索引包含 2 个域:title 和 text,text 是默认域。若想查找标题为 ”The Right Way“ 且文本内容包含 ”don’t go this way“ 的文档,可以输入:
title:"The Right Way" AND text:go
或者:
title:"The Right Way" AND go
因为 text 是默认域,所以域标识符可以省略。
注意:指定的域仅对紧跟其后的词生效,因此,如下查询:
title:The Right Way
将对 title 域仅查找 ”The“,并对默认域(当前这个例子中是指 text 域)查找 ”Right“ 和 ”Way“。
词修饰语(Term Modifiers)
Lucene 支持修饰查询词(modifying query terms)来提供多种搜索方式。
通配符搜索
Lucene 支持对单个词(single terms)(不是短语查询 phrase queries)进行单个字符和多个字符的通配搜索。
使用 ?
符号进行单个字符的通配搜索。
使用 *
符号进行多个字符的通配搜索。
单字符通配搜索用于查找替换单个字符即可匹配的词。举例来说,若要搜索 ”text“ 或 ”test“,可以如下查询:
te?t
多字符通配搜索用于查找替换0个或多个字符即可匹配的词。举例来说,若要搜索 ”test“、”tests“ 或 ”tester“,可以如下查询:
test*
也可以对词的中间部分进行通配搜索:
te*t
备注: *
或 ?
符号不能用作搜索语句的第一个字符。
正则表达式搜索
Lucene 支持正则表达式搜索,匹配斜杠(/
) 之间的模式。正则表达式的语法在不同的发布版本之间可能会有差异,目前支持的语法在 RegExp 类文档中有说明。举例来说,查找包含 ”moat“ 或 ”boat“ 的文档:
/[mb]oat/
模糊搜索
Lucene 支持基于 Damerau-Levenshtein 编辑距离的模糊搜索。在单个词的最后添加波浪符(~)即可进行模糊搜索。举例来说,使用模糊搜索查找在拼写上与 ”roam“ 近似的词:
roam~
这个查询语句会找到 foam 和 roams 这类词。
模糊搜索可以通过一个额外(可选)的参数来指定允许的最大编辑次数。这个参数值界于 0 和 2 之间,例如:
roam~1
如果未指定该参数,则默认使用 2 个编辑距离。
以前,这里还允许使用浮点数。现在这个语法已被考虑弃用,将于 Lucene 5.0 中移除。
邻近搜索
Lucene 支持查找指定距离的邻近词。在短语的最后添加拨浪符(~)即可进行邻近搜索。举例来说,在文档中搜索 ”apache“ 和 ”jakarta“ 相距 10 个词的模式:
"jakarta apache"~10
范围搜索
范围查询可以匹配到域的值在范围查询语句指定的上下界之间的所有文档。对于上下界的值,范围查询可以包含也可以不包含。排序是按照字典序进行的。
mod_date:[20020101 TO 20030101]
这个查询语句会查找 mod_date 域的值在 20020101 和 20030101 (包含上下界) 之间的文档。注意:范围查询对非日期的域也可以使用:
title:{Aida TO Carmen}
这个查询语句能查找到 title 域的值在 Aida 和 Carmen (不包含上下界)之间的所有文档。
中括号表示范围查询包含上下界,花括号表示范围查询不包含上下界。
相关性查询(Boosting a term)
Lucene 会基于文档中找到的词对匹配到的文档设置相关性的级别。可以在目标搜索词之后紧接一个脱字符 “^”,后跟一个加权系数(一个数字)来提升该搜索词的相关性权重。加权系数越高,查询命中的文档与该词的相关性越强。
你可以通过对某词进行加权来控制文档的相关性。例如,假设你正在搜索:
jakarta apache
然后希望搜索结果和词 ”jakarta“ 的相关性更强一些,则可以使用 ”^“ 符号后跟一个加权系数对这个词进行加权,即如下这样查询:
jakarta^4 apache
这会使得查找到的文档和词 ”jakarta“ 看起来相关性更强一些。你也可以对短语进行加权,如下所示:
"jakarta apache"^4 "Apache Lucene"
默认加权系数是 1。加权系统可以小于 1(比如:0.2),但必须大于 0。
布尔操作符
布尔操作符允许使用逻辑操作符组合多个词。Lucene 支持的布尔操作符包含 AND
、+
、OR
、NOT
及 -
(备注:布尔操作符必须全部是大写字母)。
OR
“OR” 操作符是默认的连接操作符。这意味着如果两个词之间没有布尔操作符,则lucene会使用 “OR” 操作符。OR 操作符链接两个词,并匹配包含其中任意一个词的文档。这相当于集合的并集操作。“||” 符合可用于替代单词 “OR”。
比如,使用如下查询语句来搜索包含 “jakarta apache” 或仅是 “jakarta” 的文档:
"jakarta apache" jakarta
或:
"jakarta apache" OR jakarta
AND
“AND” 操作符会匹配文本内容中同时存在两个要查询的词(因为 AND 是二元操作符)的文档。这相当于集合的交集操作。“&&” 符号可用于替代单词 “AND”。
比如,使用如下查询语句来搜索包含 “jakarta apache” 和 “Apache Lucene” 的文档:
"jakarta apache" AND “Apache Lucene”
+
“+”(必需)操作符要求文档的某个域中包含 “+” 符号之后的词。
比如,使用如下查询语句来搜索(必须)包含 “jakarta” 以及可能包含 “lucene”(包不包含都可以)的文档:
+jakarta lucene
NOT
”NOT“ 操作符会排除包含”NOT“之后的词的文档。这相当于集合的差集操作。也可以用”!“ 符号代替 ”NOT“。
比如,使用如下查询语句搜索包含 ”jakarta apache“ 但不包含 ”Apache Lucene“ 的文档”:
"jakarta apache" NOT "Apache Lucene"
备注:“NOT” 操作符不可以用于单个词。例如,如下搜索不会返回任何结果:
NOT "jakarta apache"
-
”-“(禁止)操作符会排除包含”-“符号之后的词的文档。
比如,使用如下查询语句来查询包含 ”jakarta apache“ 但不包含 ”Apache Lucene“ 的文档:
"jakarta apache" -"Apache Lucene"
分组
Lucene 支持使用圆括号对子句进行分组,构成子查询。这对于控制一个查询语句的布尔逻辑非常有用。
比如,使用如下查询语句来搜索包含 “jakarta” 或 “apache”,同时包含 “website” 的文档:
(jakarta OR apache) AND website
这样查询语句就没有了歧义:必须包含 ”website“,同时包含“jakarta” 或 ”apache“其中之一。
域分组
Lucene 支持使用圆括号对单个域的多个子句进行分组。
例如,若想搜索一个 title 中包含单词“return”同时包含短语“pink panther”,可以使用如下查询:
title:(+return +"pink panther")
特殊字符转义
Lucene 支持对查询语法使用的特殊字符进行转义。目前这些特殊字符如下列表所示:
+ - && || ! ( ) { } [ ] ^ " ~ * ? : \ /
在特殊字符之前加 \
来转义。例如,使用如下查询语句来搜索 (1+1):2
:
\(1\+1\)\:2