标准查询解析器

Solr 的默认查询解析器也称为“lucene”解析器。

标准查询解析器的主要优点是它支持强大且相当直观的语法,允许您创建各种结构化查询。最大的缺点是它对语法错误非常不容忍,而像DisMax 查询解析器这样的解析器旨在尽可能少地抛出错误。

标准查询解析器参数

除了常用查询参数分面参数、高亮显示参数和MoreLikeThis参数外,标准查询解析器还支持下表中描述的参数。

q

使用标准查询语法定义查询。此参数是必需的。

q.op

指定查询表达式的默认运算符。可能的值为“AND”或“OR”。

df

指定默认的可搜索字段。

sow

在空格上分割。如果设置为true,则对每个单独的空格分隔的词条分别调用文本分析。默认值为false;空格分隔的词条序列将一次性提供给文本分析,从而使对词条序列进行操作的分析过滤器(例如,多词同义词和 shingles)能够正常工作。

默认参数值在solrconfig.xml中指定,或者通过请求中的查询时值覆盖。

标准查询解析器响应

默认情况下,标准查询解析器返回的响应包含一个未命名的 <result> 块。如果使用了debug 参数,则会返回一个额外的 <lst> 块,名称为“debug”。它包含有用的调试信息,包括原始查询字符串、解析后的查询字符串以及 <result> 块中每个文档的解释信息。如果同时使用了explainOther 参数,则会为匹配该查询的所有文档提供额外的解释信息。

示例响应

本节展示标准查询解析器返回的响应示例。

下面的 URL 提交一个简单的查询,并请求 XML 响应写入器使用缩进,使 XML 响应更易读。

https://127.0.0.1:8983/solr/techproducts/select?q=id:SP2514N&wt=xml

结果

<response>
<responseHeader><status>0</status><QTime>1</QTime></responseHeader>
<result numFound="1" start="0">
 <doc>
  <arr name="cat"><str>electronics</str><str>hard drive</str></arr>
  <arr name="features"><str>7200RPM, 8MB cache, IDE Ultra ATA-133</str>
    <str>NoiseGuard, SilentSeek technology, Fluid Dynamic Bearing (FDB) motor</str></arr>
  <str name="id">SP2514N</str>
  <bool name="inStock">true</bool>
  <str name="manu">Samsung Electronics Co. Ltd.</str>
  <str name="name">Samsung SpinPoint P120 SP2514N - hard drive - 250 GB - ATA-133</str>
  <int name="popularity">6</int>
  <float name="price">92.0</float>
  <str name="sku">SP2514N</str>
 </doc>
</result>
</response>

这是一个带有有限字段列表的查询示例。

https://127.0.0.1:8983/solr/techproducts/select?q=id:SP2514N&fl=id+name&wt=xml

结果

<response>
<responseHeader><status>0</status><QTime>2</QTime></responseHeader>
<result numFound="1" start="0">
 <doc>
  <str name="id">SP2514N</str>
  <str name="name">Samsung SpinPoint P120 SP2514N - hard drive - 250 GB - ATA-133</str>
 </doc>
</result>
</response>

为标准查询解析器指定词条

发送给标准查询解析器的查询会被分解为词条和运算符。词条有两种类型:单字词条和短语词条。

  • 单字词条是一个单词,例如“test”或“hello”。

  • 短语词条是用双引号括起来的一组词,例如“hello dolly”。

多个词条可以使用布尔运算符组合在一起,形成更复杂的查询(如下所述)。

重要的是,用于查询的分析器对词条和短语的解析方式,与用于索引的分析器对词条和短语的解析方式保持一致;否则,搜索可能会产生意想不到的结果。

词条修饰符

Solr 支持各种词条修饰符,可以根据需要在搜索中增加灵活性或精确性。这些修饰符包括通配符、使搜索“模糊”或更通用的字符等等。以下各节详细介绍了这些修饰符。

通配符搜索

Solr 的标准查询解析器支持在单个词条内进行单字符和多字符通配符搜索。通配符可以应用于单个词条,但不能应用于搜索短语。

通配符搜索类型 特殊字符 示例

单字符(匹配单个字符)

?

搜索字符串 te?t 将匹配 test 和 text。

多字符(匹配零个或多个连续字符)

*

通配符搜索:tes* 将匹配 test、testing 和 tester。您还可以在词条的中间使用通配符。例如:te*t 将匹配 test 和 text。*est 将匹配 pest 和 test。

模糊搜索

Solr 的标准查询解析器支持基于 Damerau-Levenshtein 距离或编辑距离算法的模糊搜索。模糊搜索可以发现与指定词条相似的词条,而不必是完全匹配。要执行模糊搜索,请在单字词条的末尾使用波浪号 ~ 符号。例如,要搜索与“roam”拼写相似的词条,请使用模糊搜索

roam~

此搜索将匹配诸如 roams、foam 和 foams 之类的词条。它也将匹配单词“roam”本身。

可选的距离参数指定允许的最大编辑次数,介于 0 和 2 之间,默认为 2。例如

roam~1

这将匹配诸如 roams 和 foam 之类的词条,但不会匹配 foams,因为它的编辑距离为“2”。

在许多情况下,词干提取(将词条简化为共同的词干)可以产生与模糊搜索和通配符搜索类似的效果。

邻近搜索

邻近搜索查找彼此之间在特定距离内的词条。

要执行邻近搜索,请在搜索短语的末尾添加波浪号字符 ~ 和一个数值。例如,要在文档中搜索彼此之间相距 10 个单词内的 “apache” 和 “jakarta”,请使用搜索

“jakarta apache”~10

此处所指的距离是匹配指定的短语所需的词条移动次数。在上面的示例中,如果 “apache” 和 “jakarta” 在字段中相隔 10 个空格,但 “apache” 出现在 “jakarta” 之前,则需要超过 10 次词条移动才能将词条移动到一起并将 “apache” 定位在 “jakarta” 的右侧,中间有一个空格。

存在性搜索

字段的存在性搜索匹配该字段存在值的所有文档。要查询字段是否存在,只需在搜索中使用通配符代替词条即可。

field:*

如果字段有任何值,即使是通常被认为“不存在”的值(例如,NaN"" 等),也会被认为“存在”。

范围搜索

范围搜索指定字段的值范围(具有上限和下限的范围)。查询匹配指定字段或多个字段的值在范围内的文档。范围查询可以是包含上限和下限的,也可以是不包含的。排序是按字典顺序完成的,除非是在数值字段上。例如,下面的范围查询匹配所有 popularity 字段的值介于 52 和 10,000 之间的文档,包括 52 和 10,000。

popularity:[52 TO 10000]

范围查询不仅限于日期字段,甚至不限于数值字段。您还可以将范围查询与非日期字段一起使用。

title:{Aida TO Carmen}

这将查找所有标题介于 Aida 和 Carmen 之间的文档,但不包括 Aida 和 Carmen。

查询周围的括号决定其包含性。

  • 方括号 [] 表示包含范围查询,该查询匹配包括上限和下限的值。

  • 花括号 {} 表示不包含范围查询,该查询匹配上限和下限之间的值,但不包括上限和下限本身。

  • 您可以混合这些类型,使范围的一端包含,而另一端不包含。这是一个示例:count:{1 TO 10]

通配符 * 也可以用于一个或两个端点,以指定开放式范围查询。这与Lucene 的经典查询解析器存在差异

  • field:[* TO 100] 查找所有小于或等于 100 的字段值。

  • field:[100 TO *] 查找所有大于或等于 100 的字段值。

  • field:[* TO *] 查找该字段类型的值在 -Infinity 和 +Infinity 的有效值之间的任何文档。

使用通配符匹配 NaN

对于大多数字段,无界范围查询 field:[* TO *] 等同于存在性查询 field: *。但是,对于支持 NaN 值的 float/double 类型,这两个查询的执行方式不同。

  • field:* 匹配所有存在的值,包括 NaN

  • field:[* TO *] 匹配所有实际值,不包括 NaN

使用 "^" 提升词条

Solr 根据找到的词条提供匹配文档的相关性级别。要提升词条,请在您要搜索的词条末尾使用脱字符号 ^ 和提升因子(一个数字)。提升因子越高,词条的相关性越高。

提升允许您通过提升其词条来控制文档的相关性。例如,如果您要搜索

“jakarta apache”并且您希望“jakarta”词条更相关,您可以通过在词条后立即添加 ^ 符号以及提升因子来提升它。例如,您可以键入

jakarta^4 apache

这将使包含词条 jakarta 的文档看起来更相关。您还可以像在示例中那样提升短语词条

“jakarta apache”^4 “Apache Lucene”

默认情况下,提升因子为 1。虽然提升因子必须为正数,但它可以小于 1(例如,它可以是 0.2)。

使用 "^=" 的常量评分

常量评分查询是使用 <query_clause>^=<score> 创建的,它将整个子句设置为与该子句匹配的任何文档的指定评分。当您只关心特定子句的匹配,而不希望其他相关性因素(如词条频率(词条在字段中出现的次数)或反向文档频率(整个索引中词条在字段中的稀有程度的度量))时,这是可取的。

示例

(description:blue OR color:blue)^=1.0 text:shoes

查询特定字段

Solr 中索引的数据在 字段中组织,这些字段在 模式中定义。搜索可以利用字段来增加查询的精度。例如,您只能在特定字段(例如标题字段)中搜索词条。

模式将一个字段定义为默认字段。如果您在查询中未指定字段,则 Solr 仅搜索默认字段。或者,您可以在查询中指定不同的字段或字段组合。

要指定字段,请键入字段名称,后跟冒号“:”,然后键入您要在字段中搜索的词条。

例如,假设索引包含两个字段:标题和文本,并且文本是默认字段。如果您想查找一个名为 “The Right Way” 的文档,其中包含文本 “don’t go this way”,则可以在搜索查询中包含以下任一词条

title:"The Right Way" AND text:go

title:"Do it right" AND go

由于文本是默认字段,因此不需要字段指示符;因此,上面的第二个查询省略了它。

该字段仅对紧随其后的词条有效,因此查询 title:Do it right 只会在标题字段中查找“Do”。它会在默认字段(在本例中为文本字段)中查找“it”和“right”。

标准查询解析器支持的布尔运算符

布尔运算符允许您将布尔逻辑应用于查询,要求字段中存在或不存在特定词条或条件才能匹配文档。下表总结了标准查询解析器支持的布尔运算符。

布尔运算符 备选符号 描述

AND

&&

要求布尔运算符两侧的词条都存在才能匹配。

NOT

!

要求以下词条不存在。

OR

||

要求存在任一词条(或两个词条)才能匹配。

+

要求存在以下词条。

-

禁止使用以下术语(即,匹配不包含该术语的字段或文档)。- 操作符在功能上类似于布尔操作符 !。由于它被 Google 等流行的搜索引擎使用,因此某些用户社区可能更熟悉它。

布尔操作符允许通过逻辑操作符组合术语。Lucene 支持 AND、“+”、OR、NOT 和“-”作为布尔操作符。

当使用诸如 AND 或 NOT 之类的关键字指定布尔操作符时,这些关键字必须全部大写。
标准查询解析器支持上表中列出的所有布尔操作符。DisMax 查询解析器仅支持 +-

OR 操作符是默认的连接操作符。这意味着如果两个术语之间没有布尔操作符,则使用 OR 操作符。OR 操作符连接两个术语,如果文档中存在其中任何一个术语,则会找到匹配的文档。这相当于使用集合的并集。符号 || 可以用来代替单词 OR。

要搜索包含“jakarta apache”或仅包含“jakarta”的文档,请使用以下查询

"jakarta apache" jakarta

"jakarta apache" OR jakarta

布尔操作符“+”

+ 符号(也称为“必需”操作符)要求 + 符号后面的术语必须存在于至少一个文档的字段中,查询才能返回匹配项。

例如,要搜索必须包含“jakarta”并且可能包含也可能不包含“lucene”的文档,请使用以下查询

+jakarta lucene

标准查询解析器和 DisMax 查询解析器都支持此操作符。

布尔操作符 AND (“&&”)

AND 操作符匹配单个文档的文本中任何位置都存在这两个术语的文档。这相当于使用集合的交集。符号 && 可以用来代替单词 AND。

要搜索包含“jakarta apache”和“Apache Lucene”的文档,请使用以下任一查询

"jakarta apache" AND "Apache Lucene"

"jakarta apache" && "Apache Lucene"

布尔操作符 NOT (“!”)

NOT 操作符排除包含 NOT 后面的术语的文档。这相当于使用集合的差集。符号 ! 可以用来代替单词 NOT。

以下查询搜索包含短语“jakarta apache”但不包含短语“Apache Lucene”的文档

"jakarta apache" NOT "Apache Lucene"

"jakarta apache" ! "Apache Lucene"

布尔操作符“-”

- 符号或“禁止”操作符排除包含 - 符号后面的术语的文档。

例如,要搜索包含“jakarta apache”但不包含“Apache Lucene”的文档,请使用以下查询

"jakarta apache" -"Apache Lucene"

转义特殊字符

当以下字符出现在查询中时,Solr 会赋予它们特殊含义

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

要使 Solr 将这些字符中的任何一个解释为字面量,而不是特殊字符,请在该字符前面加上反斜杠字符 \。例如,要搜索 (1+1):2 而不让 Solr 将加号和括号解释为用于使用两个术语制定子查询的特殊字符,请通过在每个字符前面加上反斜杠来转义这些字符

\(1\+1\)\:2

分组术语以形成子查询

Solr 支持使用括号对子句进行分组以形成子查询。如果您想控制查询的布尔逻辑,这将非常有用。

以下查询搜索“jakarta”或“apache”以及“website”

(jakarta OR apache) AND website

这提高了查询的精度,要求术语“website”与术语“jakarta”和“apache”中的任何一个一起存在。

对字段中的子句进行分组

要将两个或多个布尔操作符应用于搜索中的单个字段,请将布尔子句放在括号内。例如,以下查询搜索包含单词“return”和短语“pink panther”的标题字段

title:(+return +"pink panther")

查询中的注释

查询字符串中支持 C 样式注释。

示例

"jakarta apache" /* 这是普通查询字符串中间的注释 */ OR jakarta

注释可以嵌套。

Lucene 的经典查询解析器和 Solr 的标准查询解析器之间的差异

Solr 的标准查询解析器最初是 Lucene 的“经典” QueryParser 的一个变体。它在以下方面有所不同

  • 可以使用 * 作为任一端点或两个端点来指定开放式范围查询,或者单独使用它作为存在查询。

    • field:[* TO 100] 查找所有小于或等于 100 的字段值

    • field:[100 TO *] 查找所有大于或等于 100 的字段值

    • field:[* TO *] 查找该字段的值介于 -InfinityInfinity 之间(不包括 NaN)的所有文档。

    • field:* 查找该字段存在的所有文档(即,具有任何值)。

  • 允许纯否定查询(所有子句都禁止)(仅作为顶级子句)

    • -inStock:false 查找所有 inStock 不为 false 的字段值

    • -field:* 查找该字段没有值的所有文档。

  • 支持使用本地参数语法将任何类型的查询解析器作为嵌套子句嵌入 Solr 查询(子查询)。

    • inStock:true OR {!dismax qf='name manu' v='ipod'}

      注意:请注意不要在开头就用 {! 开始查询,这会更改整个查询字符串的解析,如果还有其他子句,这可能不是您想要的。因此,如果上面的示例反过来,子查询在前,则在没有前导空格的情况下,将无法按预期工作。

      也可以使用魔术字段 _query_ 进行子查询,也可以使用魔术字段 _val_ 进行函数查询,但由于不太清楚,因此应将其视为已弃用。示例:_val_:"recip(rord(myfield),1,2,3)"

  • 支持特殊的 filter(…​) 语法,以指示某些查询子句应缓存在过滤器缓存中(作为常量分数布尔查询)。这允许在其他查询中缓存和重用子查询。例如,inStock:true 将在以下三个查询中被缓存和重用

    • q=features:songs OR filter(inStock:true)

    • q=+manu:Apple +filter(inStock:true)

    • q=+manu:Apple & fq=inStock:true

      这甚至可以用来缓存复杂过滤器查询的单个子句。在下面的第一个查询中,将向过滤器缓存添加 3 个项(顶级 fq 和两个 filter(…​) 子句),在第二个查询中,将有 2 个缓存命中,以及一个新的缓存插入(对于新的顶级 fq

    • q=features:songs & fq=+filter(inStock:true) +filter(price:[* TO 100])

    • q=manu:Apple & fq=-filter(inStock:true) -filter(price:[* TO 100])

  • 范围查询(“[a TO z]”)、前缀查询(“a*”)和通配符查询(“a*b”)是恒定得分的(所有匹配的文档都获得相同的分数)。不使用得分因子 TF、IDF、索引提升和“coord”。匹配的术语数量没有限制(就像过去版本的 Lucene 中那样)。

  • 常量得分查询是通过 <query_clause>^=<score> 创建的,它将整个子句设置为任何匹配该子句的文档的指定分数

    • q=(description:blue color:blue)^=1.0 title:blue^=5.0

指定日期和时间

针对基于日期的字段的查询必须使用适当的日期格式。精确日期值的查询将需要引用或转义,因为 : 是用于表示字段查询的解析器语法

  • createdate:1976-03-06T23\:59\:59.999Z

  • createdate:"1976-03-06T23:59:59.999Z"

  • createdate:[1976-03-06T23:59:59.999Z TO *]

  • createdate:[1995-12-31T23:59:59.999Z TO 2007-03-06T00:00:00Z]

  • timestamp:[* TO NOW]

  • pubdate:[NOW-1YEAR/DAY TO NOW/DAY+1DAY]

  • createdate:[1976-03-06T23:59:59.999Z TO 1976-03-06T23:59:59.999Z+1YEAR]

  • createdate:[1976-03-06T23:59:59.999Z/YEAR TO 1976-03-06T23:59:59.999Z]