标准查询解析器
Solr 的默认查询解析器也称为“lucene
”解析器。
标准查询解析器的主要优势在于它支持强大且相当直观的语法,允许您创建各种结构化查询。最大的缺点是它对语法错误非常不宽容,而与 DisMax 查询解析器 之类的东西相比,后者旨在尽可能少地引发错误。
标准查询解析器参数
除了 通用查询参数、分面 参数、高亮 参数和 MoreLikeThis 参数之外,标准查询解析器还支持下表中描述的参数。
q
-
使用标准查询语法定义查询。此参数是必需的。
q.op
-
指定查询表达式的默认运算符。可能的值为“AND”或“OR”。
df
-
指定默认可搜索字段。
sow
-
按空格拆分。如果设置为
true
,则为每个单独的空格分隔的术语单独调用文本分析。默认值为false
;空格分隔的术语序列将一次性提供给文本分析,从而启用对术语序列进行操作的分析过滤器的正确功能,例如多词同义词和分词。
默认参数值在 solrconfig.xml
中指定,或由请求中的查询时间值覆盖。
标准查询解析器响应
默认情况下,标准查询解析器的响应包含一个未命名的 <result>
块。如果使用了 debug
参数,则会返回一个附加的 <lst>
块,使用名称“debug”。这将包含有用的调试信息,包括原始查询字符串、已解析的查询字符串以及 <result> 块中每个文档的说明信息。如果还使用了 explainOther
参数,则会为匹配该查询的所有文档提供附加的说明信息。
示例响应
本部分提供了标准查询解析器的响应示例。
下面的 URL 提交了一个简单查询,并请求 XML 响应编写器使用缩进使 XML 响应更具可读性。
http://localhost: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>
下面是一个具有有限字段列表的查询示例。
http://localhost: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 的标准查询解析器支持基于 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(含)之间的文档。
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 值对于大多数字段,无界范围查询
|
使用“^”提升术语
Solr 根据找到的术语提供匹配文档的相关性级别。要提升术语,请使用脱字符号 ^
和提升因子(一个数字),放在要搜索的术语的末尾。提升因子越高,术语的相关性就越高。
提升允许您通过提升其术语来控制文档的相关性。例如,如果您正在搜索
"jakarta apache",并且您希望术语 "jakarta" 更相关,您可以通过在术语后立即添加 ^ 符号和提升因子来提升它。例如,您可以输入
jakarta^4 apache
这将使包含术语 jakarta 的文档显得更相关。您还可以像示例中那样提升短语术语
"jakarta apache"^4 "Apache Lucene"
默认情况下,提升因子为 1。尽管提升因子必须为正数,但它可以小于 1(例如,可以为 0.2)。
查询特定字段
架构将一个字段定义为默认字段。如果您在查询中未指定字段,Solr 仅搜索默认字段。或者,您可以在查询中指定不同的字段或字段组合。
要指定字段,请键入字段名称,后跟冒号 “:” 和您在字段中搜索的术语。
例如,假设一个索引包含两个字段,即 title 和 text,并且 text 是默认字段。如果您想找到包含文本“don’t go this way”的文档“The Right Way”,您可以在搜索查询中包含以下任一术语
title:"The Right Way" AND text:go
title:"Do it right" AND go
由于 text 是默认字段,因此不需要字段指示符;因此,上面的第二个查询省略了它。
该字段仅对它直接前面的术语有效,因此查询 title:Do it right
仅会在 title 字段中找到“Do”。它会在默认字段(在本例中为 text 字段)中找到“it”和“right”。
标准查询解析器支持的布尔运算符
布尔运算符允许您将布尔逻辑应用于查询,要求字段中存在或不存在特定术语或条件才能匹配文档。下表总结了标准查询解析器支持的布尔运算符。
布尔运算符 | 替代符号 | 说明 |
---|---|---|
AND |
|
要求布尔运算符两侧的两个术语都存在才能匹配。 |
NOT |
|
要求不存在以下术语。 |
OR |
|
要求存在任一术语(或两个术语)才能匹配。 |
|
要求存在以下术语。 |
|
|
禁止以下术语(即匹配不包含该术语的字段或文档)。 |
布尔运算符允许通过逻辑运算符组合术语。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"
lucene 的经典查询解析器与 solr 的标准查询解析器的差异
Solr 的标准查询解析器最初是 lucene 的“经典”QueryParser 的一个变体。它在以下方面有所不同
-
*
可用于一个或两个端点,以指定开区间范围查询,或本身用作存在查询。-
field:[* TO 100]
查找所有小于或等于 100 的字段值 -
field:[100 TO *]
查找所有大于或等于 100 的字段值 -
field:[* TO *]
查找所有字段值在-Infinity
和Infinity
之间(不包括NaN
)的文档。 -
field:*
查找所有字段存在的文档(即具有任何值)。
-
-
允许纯否定查询(禁止所有子句)(仅作为顶级子句)
-
-inStock:false
查找所有 inStock 不为 false 的字段值 -
-field:*
查找所有没有字段值的文档。
-
-
支持使用任何类型的查询解析器作为嵌套子句的嵌入式 Solr 查询(子查询),并使用 local-params 语法。
-
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]