Lucene 查询解析器语法(译)

2019-09-04 三
By xiayf

原文:Query Parser Syntax

概览

Lucene 除了提供 API 方便开发者创建查询请求,还通过一个查询解析器(一个词法分析器,使用 JavaCC 将一个字符串翻译成一个 Lucene 查询)提供一种功能丰富的查询语言。

一般来说,查询解析器支持的语法在不同发布版本之间可能会有变化。当前这个文档页面描述的是当前这个发布版本的语法。如果你正在使用一个不同版本的 Lucene,请参考该版本自带的 docs/queryparsersyntax.html 文档。

在选择使用这个查询解析器之前,请考虑以下 3 点:

  1. 如果你准备以编程的方式生成一个查询字符串,然后使用查询解析器来解析它。那么,你应该认真考虑一下是否应该直接使用查询 API 来构建查询。换句话说,查询解析器专门用于人类输入的文本,而不是程序生成的文本。
  2. 不可分词(untokenized)的域(译者注:抱歉,此处没太理解)最好直接添加到查询中,而不是通过查询解析器来解析。如果一个域的值是通过应用自动生成的,那么应该为这个域自动生成查询子句。分析器(查询解析器所使用的)是专门用于将人类输入的文本转换成一些词(terms),那么程序自动生成的值,也应该由程序自动添加到查询中。
  3. 从查询形式来看,如果域的值是普通文本,则应该使用查询解析器。所有其它值类型,比如:日期范围、关键词等等,最好通过查询 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+ORNOT-(备注:布尔操作符必须全部是大写字母)。

OR

“OR” 操作符是默认的连接操作符。这意味着如果两个词之间没有布尔操作符,则使用 “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