其他查询解析器

除了主要查询解析器之外,还有其他几个查询解析器,可以用来代替或与主要解析器结合使用,以满足特定目的。

本节详细介绍了其他解析器,并给出了如何使用它们的示例。

其中许多解析器的表达方式与局部参数相同。

块连接查询解析器

块连接查询解析器与嵌套文档一起使用,以查询父级和/或子级。

这些解析器在块连接查询解析器部分中进行了详细介绍。

布尔查询解析器

BoolQParser创建一个 Lucene BooleanQuery,它是其他查询的布尔组合。子查询及其类型化出现指示了如何匹配和评分文档。

参数

must

可选

默认值:无

必须出现在匹配文档中并有助于评分的查询列表。

must_not

可选

默认值:无

不得出现在匹配文档中的查询列表。

should

可选

默认值:无

查询列表应该出现在匹配文档中。对于没有must查询的 BooleanQuery,一个或多个should查询必须与文档匹配,才能使 BooleanQuery 匹配。

filter

可选

默认值:无

必须出现在匹配文档中的查询列表。但是,与must不同,过滤查询的分数会被忽略。此外,这些查询缓存在过滤器缓存中。要避免缓存,请添加cache=false作为局部参数,或将"cache":"false"属性添加到底层查询 DSL 对象。

mm

可选

默认值:0

必须匹配的可选子句数。默认情况下,匹配不需要任何可选子句(除非没有必需子句)。如果设置此参数,则需要指定数量的 should 子句。如果未设置此参数,则布尔查询的通常规则仍适用于搜索时间 - 即,不包含任何必需子句的布尔查询仍必须至少匹配一个可选子句。

excludeTags

可选

默认值:无

用于从上述参数中排除查询的标签的逗号分隔列表。请参阅下面的说明。

示例

{!bool must=foo must=bar}
{!bool filter=foo should=bar}
{!bool should=foo should=bar should=qux mm=2}

参数也可能是多值引用。上面的前一个示例等效于

q={!bool must=$ref}&ref=foo&ref=bar

可以通过标签排除引用的查询。总体思路类似于 排除 facet 中的 fq

q={!bool must=$ref excludeTags=t2}&ref={!tag=t1}foo&ref={!tag=t2}bar

由于稍后的查询通过 t2 排除,因此结果查询等效于

q={!bool must=foo}

提升查询解析器

BoostQParser 扩展了 QParserPlugin 并从输入值创建提升查询。主值是要“包装”和“提升”的任何查询——只有与该查询匹配的文档才会与该解析器生成的最终查询匹配。参数 b 是针对与原始查询匹配的每个文档评估的 函数,并且函数的结果将乘以该文档的最终得分。

提升查询解析器示例

创建一个查询 name:foo,该查询由函数查询 log(popularity) 提升(分数相乘)

q={!boost b=log(popularity)}name:foo

创建一个查询 name:foo,其分数乘以数字 price 字段的倒数——有效地“降级”具有较高 price 的文档,方法是降低其最终分数

// NOTE: we "add 1" to the denominator to prevent divide by zero
q={!boost b=div(1,add(1,price))}name:foo

query(…​) 函数对于希望通过文档从另一个查询获得的分数乘以(或除以)与主查询匹配的每个文档的分数的情况特别有用。

此示例使用本地参数变量创建一个查询 name:foo,该查询由独立指定的查询 category:electronics 的得分提升

q={!boost b=query($my_boost)}name:foo
my_boost=category:electronics

折叠查询解析器

CollapsingQParser 实际上是一个后置过滤器,当结果集中不同组的数量较高时,它比 Solr 的标准方法提供更高效的字段折叠。

此解析器将结果集折叠为每组一个文档,然后将结果集转发给其余搜索组件。因此,所有下游组件(分面、高亮显示等)都将使用折叠后的结果集。

有关使用 CollapsingQParser 的详细信息,请参阅折叠和展开结果部分。

复杂短语查询解析器

ComplexPhraseQParser 使用 Lucene 的ComplexPhraseQueryParser为短语查询提供对通配符、OR 等的支持。

在底层,此查询解析器使用 Span 查询组(例如 spanNear、spanOr 等),并且受该系列解析器的相同限制。

参数

inOrder

可选

默认值:true

设置为 true 以强制短语查询按指定顺序匹配术语。

df

可选

默认值:无

默认搜索字段。

示例

{!complexphrase inOrder=true}name:"Jo* Smith"
{!complexphrase inOrder=false}name:"(john jon jonathan~) peters*"

有序和无序复杂短语查询的混合

+_query_:"{!complexphrase inOrder=true}manu:\"a* c*\"" +_query_:"{!complexphrase inOrder=false df=name}\"bla* pla*\""

复杂短语解析器限制

性能对与模式关联的唯一术语的数量敏感。例如,搜索 “a*” 将为指定字段中以单个字母 'a' 开头的索引中的所有术语形成一个较大的 OR 子句(从技术上讲,是包含许多术语的 SpanOr)。谨慎地将通配符限制为至少两个或最好三个字母作为前缀可能是明智的。允许非常短的前缀可能会导致返回许多低质量文档。

请注意,它还支持前导通配符 “*a”,并会产生相应的性能影响。在索引时分析中应用ReversedWildcardFilterFactory通常是一个好主意。

复杂短语解析器中的 MaxBooleanClauses

由于上述术语扩展,您可能需要在 solrconfig.xml 中增加 MaxBooleanClauses

<maxBooleanClauses>4096</maxBooleanClauses>

此属性在查询大小调整和预热部分中有更详细的描述。

复杂短语解析器中的停用词

不建议对该查询解析器使用停用词消除。

假设我们为某个集合向 stopwords.txt 添加术语 theupto,并在名为 “features” 的字段中索引包含文本 “Stores up to 15,000 songs, 25,00 photos, or 150 yours of video” 的文档。

虽然下面的查询未使用此解析器

 q=features:"Stores up to 15,000"

返回了文档。下一个查询确实使用了复杂短语查询解析器,如以下查询

 q=features:"sto* up to 15*"&defType=complexphrase

返回该文档,因为 SpanNearQuery 无法很好地处理停用词,类似于 PhraseQuery。如果您必须为您的用例移除停用词,请使用自定义过滤器工厂或可能是一个自定义同义词过滤器,它将给定的停用词缩减为一些不可能的标记。

使用复杂短语解析器转义

转义时必须特别小心:双引号之间的子句(通常是整个查询)被解析两次,这些部分必须被转义两次,例如,"foo\\: bar\\^"

字段查询解析器

FieldQParser 扩展了 QParserPlugin,并从输入值创建了一个字段查询,应用文本分析并在适当的情况下构建一个短语查询。参数 f 是要查询的字段。

示例

{!field f=myfield}Foo Bar

此示例创建了一个短语查询,其中“foo”后跟“bar”(假设 myfield 的分析器是一个文本字段,其分析器按空格和词干进行拆分)。这通常等效于 Lucene 查询解析器表达式 myfield:"Foo Bar"

过滤器查询解析器

语法为

q={!filters param=$fqs excludeTags=sample}field:text&
fqs=COLOR:Red&
fqs=SIZE:XL&
fqs={!tag=sample}BRAND:Foo

等效于

q=+field:text +COLOR:Red +SIZE:XL

param 本地参数使用“$”语法来引用一些查询,其中 excludeTags 可能省略其中一些查询。

函数查询解析器

FunctionQParser 扩展了 QParserPlugin,并从输入值创建了一个函数查询。这只是在 Solr 中使用函数查询的一种方式;对于另一种更集成的途径,请参阅 函数查询 部分。

示例

{!func}log(foo)

函数范围查询解析器

FunctionRangeQParser 扩展了 QParserPlugin,并创建了一个函数范围查询。这也称为 frange,如下面的示例所示。

参数

l

可选

默认值:无

下界。

u

可选

默认值:无

上界。

incl

可选

默认值:true

包括下界。

incu

可选

默认值:true

包括上界。

示例

{!frange l=1000 u=50000}myfield
 fq={!frange l=0 u=2.2} sum(user_ranking,editor_ranking)

这两个示例都通过已声明字段或函数查询中找到的一系列值来限制结果。在第二个示例中,我们执行一个求和计算,然后定义仅在 0 到 2.2 之间的值应返回给用户。

有关函数范围查询的更多信息,请参阅 Yonik Seeley 的介绍性博文 Solr 1.4 中的函数范围

图形查询解析器

graph 查询解析器对从由包装查询标识的一组根文档“可达”的所有文档执行广度优先、循环感知的图形遍历。

图形根据文档之间基于在查询中指定为 fromto 字段中找到的术语的链接构建。

支持的字段类型是启用了 docValues 的点字段,或具有 indexed=truedocValues=true 的字符串字段。

对于 indexed=falsedocValues=true 的字符串字段,请参阅 SortedDocValuesField.newSlowSetQuery() 的 javadoc,了解其性能特征,因此 indexed=true 在大多数用例中表现得更好。

图形查询参数

to

可选

默认值:edge_ids

要检查以识别图形遍历的传出边的匹配文档的字段名称。

from

可选

默认值:node_id

要检查以识别传入图形边的候选文档中的字段名称。

traversalFilter

可选

默认值:无

可以提供的可选查询,以限制要遍历的文档的范围。

maxDepth

可选

默认值:-1(无限制)

指定广度优先搜索图形的深度,从初始查询开始。

returnRoot

可选

默认值:true

布尔值,指示是否应将与原始查询匹配的文档(以定义图形的起点)包含在最终结果中。

returnOnlyLeaf

可选

默认值:false

布尔值,指示是否应过滤查询结果,以便仅返回没有传出边的文档。

useAutn

可选

默认值:false

布尔值,指示是否应为广度优先搜索的每次迭代编译自动机,这对于某些图形可能更快。

图形查询限制

graph 解析器仅适用于单节点 Solr 安装,或使用恰好 1 个分片的 SolrCloud 和用户管理的集群。

图形查询示例

要了解图形解析器的工作原理,请考虑以下有向循环图,其中包含 8 个节点(A 到 H)和 9 条边(1 到 9)

image

将此图形建模为 Solr 文档的一种方法是,为每个节点创建一个文档,其中多值字段标识每个节点的传入和传出边

curl -H 'Content-Type: application/json' 'http://localhost:8983/solr/my_graph/update?commit=true' --data-binary '[
  {"id":"A","foo":  7, "out_edge":["1","9"],  "in_edge":["4","2"]  },
  {"id":"B","foo": 12, "out_edge":["3","6"],  "in_edge":["1"]      },
  {"id":"C","foo": 10, "out_edge":["5","2"],  "in_edge":["9"]      },
  {"id":"D","foo": 20, "out_edge":["4","7"],  "in_edge":["3","5"]  },
  {"id":"E","foo": 17, "out_edge":[],         "in_edge":["6"]      },
  {"id":"F","foo": 11, "out_edge":[],         "in_edge":["7"]      },
  {"id":"G","foo":  7, "out_edge":["8"],      "in_edge":[]         },
  {"id":"H","foo": 10, "out_edge":[],         "in_edge":["8"]      }
]'

使用上面显示的模型,以下查询演示了从节点 A 可到达的所有节点的简单遍历

http://localhost:8983/solr/my_graph/query?fl=id&q={!graph+from=in_edge+to=out_edge}id:A
"response":{"numFound":6,"start":0,"docs":[
   { "id":"A" },
   { "id":"B" },
   { "id":"C" },
   { "id":"D" },
   { "id":"E" },
   { "id":"F" } ]
}

我们还可以使用 traversalFilter 将图形遍历限制为 foo 字段中最大值为 15 的节点。在这种情况下,这意味着 D、E 和 F 被排除在外——F 的值为 foo=11,但由于遍历跳过了 D,因此无法到达

http://localhost:8983/solr/my_graph/query?fl=id&q={!graph+from=in_edge+to=out_edge+traversalFilter='foo:[*+TO+15]'}id:A
...
"response":{"numFound":3,"start":0,"docs":[
   { "id":"A" },
   { "id":"B" },
   { "id":"C" } ]
}

到目前为止显示的示例都使用单个文档的查询("id:A")作为图形遍历的根节点,但任何查询都可以用来识别多个文档以用作根节点。下一个示例演示如何使用 maxDepth 参数查找所有距离根节点最多只有一条边的节点,且 foo 字段中的值小于或等于 10

http://localhost:8983/solr/my_graph/query?fl=id&q={!graph+from=in_edge+to=out_edge+maxDepth=1}foo:[*+TO+10]
...
"response":{"numFound":6,"start":0,"docs":[
   { "id":"A" },
   { "id":"B" },
   { "id":"C" },
   { "id":"D" },
   { "id":"G" },
   { "id":"H" } ]
}

简化模型

上述示例中使用的文档和字段建模明确枚举了每个节点的所有传出和传入边,以帮助确切演示“from”和“to”参数的工作原理,并让您了解可能的情况。通过使用这些字段的多个集合来识别传入和传出边,可以对包含集合中部分或所有文档的许多独立有向图进行建模。

但在许多情况下,还可以极大地简化所使用的模型。

例如,上面图表中显示的相同图形可以通过 Solr 文档建模,这些文档表示每个节点,并且只知道它们链接到的节点的 ID,而不知道任何有关传入链接的信息

curl -H 'Content-Type: application/json' 'http://localhost:8983/solr/alt_graph/update?commit=true' --data-binary '[
  {"id":"A","foo":  7, "out_edge":["B","C"] },
  {"id":"B","foo": 12, "out_edge":["E","D"] },
  {"id":"C","foo": 10, "out_edge":["A","D"] },
  {"id":"D","foo": 20, "out_edge":["A","F"] },
  {"id":"E","foo": 17, "out_edge":[]        },
  {"id":"F","foo": 11, "out_edge":[]        },
  {"id":"G","foo":  7, "out_edge":["H"]     },
  {"id":"H","foo": 10, "out_edge":[]        }
  ]'

使用此替代文档模型,仍然可以执行上面演示的所有相同查询,只需更改“from”参数,用“id”字段替换“in_edge”字段即可

http://localhost:8983/solr/alt_graph/query?fl=id&q={!graph+from=id+to=out_edge+maxDepth=1}foo:[*+TO+10]
...
"response":{"numFound":6,"start":0,"docs":[
   { "id":"A" },
   { "id":"B" },
   { "id":"C" },
   { "id":"D" },
   { "id":"G" },
   { "id":"H" } ]
}

哈希范围查询解析器

哈希范围查询解析器将返回包含字段的文档,该字段包含将哈希到特定范围的值。在使用 method=crossCollection 时,联接查询解析器使用此方法。哈希范围查询解析器为此查询解析器将操作的每个字段设置了一个每段缓存。

在使用哈希范围查询解析器指定最小/最大哈希范围和字段名称时,只会返回包含哈希到该范围内的字段值的文档。如果您要查询非常大的结果集,您可以查询各种哈希范围,以通过每个范围请求返回部分文档。

跨集合联接情况下,哈希范围查询解析器用于确保每个分片仅获取最终位于该分片上的联接键集。

此查询解析器使用 MurmurHash3_x86_32。这与 Solr 中的默认复合 ID 路由器的默认哈希相同。

哈希范围参数

f

可选

默认值:无

要操作的字段名称。此字段应启用 docValues,并且应为单值。

l

可选

默认值:无

查询的哈希范围的下限。

u

可选

默认值:无

查询的哈希范围的上限。

哈希范围示例

{!hash_range f="field_name" l="0" u="12345"}

哈希范围缓存配置

哈希范围查询解析器使用特殊缓存来提高查询速度。应将以下内容添加到您要对其执行哈希范围查询的各个字段的 solrconfig.xml 中。请注意,缓存的名称应该是以“hash_”为前缀的字段名称。

<cache name="hash_field_name"
       class="solr.LRUCache"
       size="128"
       initialSize="0"
       regenerator="solr.NoOpRegenerator"/>

联接查询解析器

联接查询解析器允许用户运行查询,以规范文档之间的关系,类似于 SQL 风格的联接。

此查询解析器的详细信息在联接查询解析器部分中。

学习对查询解析器进行排名

LTRQParserPlugin 是一个特殊用途的解析器,用于使用基于机器学习模型的更复杂的排名查询对简单查询的顶部结果进行重新排名。

示例

{!ltr model=myModel reRankDocs=100}

有关使用 LTRQParserPlugin 的详细信息,请参阅学习对排名部分。

最大分数查询解析器

MaxScoreQParser 扩展了 LuceneQParser,但返回了子句中的最大得分。它通过将所有 SHOULD 子句包装在 DisjunctionMaxQuery 中(tie=1.0)来实现此目的。任何 MUSTPROHIBITED 子句都按原样传递。非布尔查询(例如 NumericRange)将传递到 LuceneQParser 解析器行为。

示例

{!maxscore tie=0.01}C OR (D AND E)

MinHash 查询解析器

MinHashQParser 为使用 MinHashFilterFactory 分析的字段构建查询。查询衡量查询字符串和 MinHash 字段之间的 Jaccard 相似性;如果需要,允许进行更快速、近似的匹配。解析器支持两种操作模式。第一种是通过正常分析从文本生成标记;第二种是提供显式标记。

目前,查询返回的分数反映了匹配的顶级元素的数量,并且在 0 和 1 之间归一化。

sim

必需

默认值:无

最小相似性。默认行为是查找大于零的任何相似性。0.01.0 之间的一个数字。

tp

可选

默认值:1.0

所需的真阳性率。对于低于 1.0 的值,可以使用经过优化且更快的带状查询。带状行为取决于所请求的 simtp 的值。

field

可选

默认值:无

对 MinHash 值进行索引的字段。该字段通常用于分析提供给查询解析器的文本。它还用于查询字段。

sep

可选

默认值:“”(空字符串)

一个分隔符字符串。如果提供了非空分隔符字符串,则查询字符串将被解释为由分隔符字符串分隔的预分析值列表。在这种情况下,不会对字符串执行其他分析:令牌按原样使用。

analyzer_field

可选

默认值:无

此参数可用于定义如何分析文本,不同于查询字段。当使用预分析字符串 field 来存储 MinHash 值时,它用于分析查询文本。请参见下面的示例。

此查询解析器已使用名称 min_hash 注册。

经过分析的字段示例

典型分析

 <fieldType name="text_min_hash" class="solr.TextField" positionIncrementGap="100">
    <analyzer>
      <tokenizer class="solr.ICUTokenizerFactory"/>
      <filter class="solr.ICUFoldingFilterFactory"/>
      <filter class="solr.ShingleFilterFactory" minShingleSize="5" outputUnigrams="false" outputUnigramsIfNoShingles="false" maxShingleSize="5" tokenSeparator=" "/>
      <filter class="org.apache.lucene.analysis.minhash.MinHashFilterFactory" bucketCount="512" hashSetSize="1" hashCount="1"/>
    </analyzer>
  </fieldType>
...

  <field name="min_hash_analysed" type="text_min_hash" multiValued="false" indexed="true" stored="false" />

在此,输入文本按空格拆分,标记归一化,将结果标记流组装成所有 5 个单词分片的流,然后进行哈希处理。每个 512 个存储桶中哈希值最低的哈希值将被保留并作为输出标记生成。

对此字段的查询需要生成至少一个分片,因此需要 5 个不同的标记。

查询示例

 {!min_hash field="min_hash_analysed"}At least five or more tokens

 {!min_hash field="min_hash_analysed" sim="0.5"}At least five or more tokens

 {!min_hash field="min_hash_analysed" sim="0.5" tp="0.5"}At least five or more tokens

预分析字段示例

在此,MinHash 是预先计算的,很可能使用 Lucene 分析,如下所示。从架构中获取分析器会更加谨慎。

    ICUTokenizerFactory factory = new ICUTokenizerFactory(Collections.EMPTY_MAP);
    factory.inform(null);
    Tokenizer tokenizer = factory.create();
    tokenizer.setReader(new StringReader(text));
    ICUFoldingFilterFactory filter = new ICUFoldingFilterFactory(Collections.EMPTY_MAP);
    TokenStream ts = filter.create(tokenizer);
    HashMap<String, String> args = new HashMap<>();
    args.put("minShingleSize", "5");
    args.put("outputUnigrams", "false");
    args.put("outputUnigramsIfNoShingles", "false");
    args.put("maxShingleSize", "5");
    args.put("tokenSeparator", " ");
    ShingleFilterFactory sff = new ShingleFilterFactory(args);
    ts = sff.create(ts);
    HashMap<String, String> args2 = new HashMap<>();
    args2.put("bucketCount", "512");
    args2.put("hashSetSize", "1");
    args2.put("hashCount", "1");
    MinHashFilterFactory mhff = new MinHashFilterFactory(args2);
    ts = mhff.create(ts);

    CharTermAttribute termAttribute = ts.getAttribute(CharTermAttribute.class);

    ts.reset();
    while (ts.incrementToken())
    {
        char[] buff = termAttribute.buffer();
        ...
     }
     ts.end();

该架构将仅定义一个多值字符串值和一个可选字段,以便在分析时使用 - 类似于上述内容。

 <field name="min_hash_string" type="strings" multiValued="true" indexed="true" stored="true"/>

 <!-- Optional -->
 <field name="min_hash_analysed" type="text_min_hash" multiValued="false" indexed="true" stored="false"/>

 <fieldType name="strings" class="solr.StrField" sortMissingLast="true" multiValued="true"/>

 <!-- Optional -->
 <fieldType name="text_min_hash" class="solr.TextField" positionIncrementGap="100">
    <analyzer>
      <tokenizer class="solr.ICUTokenizerFactory"/>
      <filter class="solr.ICUFoldingFilterFactory"/>
      <filter class="solr.ShingleFilterFactory" minShingleSize="5" outputUnigrams="false" outputUnigramsIfNoShingles="false" maxShingleSize="5" tokenSeparator=" "/>
      <filter class="org.apache.lucene.analysis.minhash.MinHashFilterFactory" bucketCount="512" hashSetSize="1" hashCount="1"/>
    </analyzer>
  </fieldType>

查询示例

{!min_hash field="min_hash_string" sep=","}HASH1,HASH2,HASH3

{!min_hash field="min_hash_string" sim="0.9" analyzer_field="min_hash_analysed"}Lets hope the config and code for analysis are in sync

也可以使用已知哈希值查询分析字段(上述内容的相反操作)

{!min_hash field="min_hash_analysed" analyzer_field="min_hash_string" sep=","}HASH1,HASH2,HASH3

预分析字段意味着哈希值可以按文档恢复,而不是重新哈希处理。返回存储的 minhash 字段的初始查询阶段可以随后使用 min_hash 查询来查找类似文档。

带状查询

给定上述配置,查询解析器的默认行为是生成布尔查询,并将 512 个常量得分项查询一起进行 OR 操作:每个哈希一个。在这种情况下,如果一个哈希匹配,则生成 1 分,如果所有哈希都匹配,则生成 512 分。

带状查询混合了合取和析取。我们可以有 256 个带,每个带由两个查询 AND 在一起,128 个带由 4 个哈希 AND 在一起,依此类推。带越少,查询性能越高,但我们可能会错过一些匹配项。速度和准确性之间存在权衡。对于 64 个带,得分范围为 0 到 64(一起进行 OR 操作的带数)

给定所需的相似性和可接受的真阳性率,查询解析器会计算适当的带大小[1]。它会找到受以下条件约束的最小带数

如果没有足够的哈希值来填充查询的最后一个带,它将环绕到开头。

关于相似性的说明

低相似性可能是有意义的。5 个单词哈希的数量很大。即使是单个匹配也可能表明在含义、风格或结构上存在某种相似性。

延伸阅读

有关一般性介绍,请参阅“海量数据集挖掘”[1]

对于约 1500 个单词的文档,预计索引大小开销约为 10%;你的实际情况可能会有所不同。预计 512 个哈希可以很好地表示约 2500 个单词。

在初始论文[2]中提出了使用一组 MinHash 值,但提供了对 Jaccard 相似性的偏差估计。在某些情况下,这种偏差可能是一件好事。旋转和短文档也是如此。该实现源自后来工作[3]中提出的无偏差方法。

[1] Leskovec, Jure;Rajaraman, Anand & Ullman, Jeffrey D. “挖掘海量数据集”,剑桥大学出版社;第 2 版(2014 年 12 月 29 日),第 3 章,ISBN:9781107077232。

[2] Broder, Andrei Z. (1997),“关于文档的相似性和包含性”,序列的压缩和复杂性:意大利萨莱诺阿马尔菲海岸波西塔诺会议论文集,1997 年 6 月 11-13 日(PDF),IEEE,第 21-29 页,doi:10.1109/SEQUEN.1997.666900。

[3] Shrivastava, Anshumali & Li, Ping (2014),“改进每种排列哈希的致密化”,第 30 届人工智能不确定性会议 (UAI),加拿大魁北克魁北克市,2014 年 7 月 23-27 日,AUAI,第 225-234 页,http://www.auai.org/uai2014/proceedings/individuals/225.pdf

更像此查询解析器

MLTQParser 能够检索与给定文档相似的文档。它使用 Lucene 现有的 MoreLikeThis 逻辑,并且还可以在 SolrCloud 模式下工作。有关如何使用此查询解析器的信息与有关 MoreLikeThis 的文档一起,在 MoreLikeThis 查询解析器 部分中。

嵌套查询解析器

NestedParser 扩展了 QParserPlugin,并创建了一个嵌套查询,该查询能够通过本地参数重新定义其类型。这对于在配置中指定默认值并让客户端间接引用它们非常有用。

示例

{!query defType=func v=$q1}

如果 q1 参数是价格,则查询将是对价格字段的函数查询。如果 q1 参数是 \{!lucene}inStock:true}},则从与 inStock=true 文档匹配的 Lucene 语法字符串创建术语查询。这些参数将在 solrconfig.xml 中的 defaults 部分中定义

<lst name="defaults">
  <str name="q1">{!lucene}inStock:true</str>
</lst>

有关嵌套查询的可能性的更多信息,请参阅 Yonik Seeley 的博客文章 Solr 中的嵌套查询

神经查询解析器

Solr 中目前有一个查询解析器可提供神经搜索:knn

KNN 代表 k 近邻。

详细信息在 密集向量搜索 部分中有进一步说明。

有效负载查询解析器

这些查询解析器利用索引期间对词条编码的有效负载。可以使用 DelimitedPayloadTokenFilterNumericPayloadTokenFilter 对词条编码有效负载。

有效负载评分解析器

PayloadScoreQParser 将每个匹配词条的数字(整数或浮点数)有效负载纳入评分中。主查询从字段类型的查询分析中解析为 SpanQuery,具体取决于以下 operator 参数的值。

此解析器接受以下参数

f

必需

默认值:无

要使用的字段。

func

必需

默认值:无

有效负载函数。选项有:minmaxaveragesum

operator

可选

默认值:无

搜索运算符。选项有:* or 将生成 SpanTermQuerySpanOrQuery,具体取决于发出的标记数量。* phrase 将生成 SpanTermQuery 或有序的零 slop SpanNearQuery,具体取决于发出的标记数量。

includeSpanScore

可选

默认值:false

如果为 true,则将计算出的有效负载因子乘以原始查询的评分。如果为 false,则计算出的有效负载因子就是评分。

示例

{!payload_score f=my_field_dpf v=some_term func=max}
{!payload_score f=payload_field func=sum operator=or}A B C

有效负载检查解析器

PayloadCheckQParser 仅在匹配的词条与有效负载也有指定关系时才匹配。默认关系为相等,但也可以执行不等式匹配。对于这两个解析器,主查询都直接从字段类型的查询分析解析为 SpanQuery。生成的 SpanQuery 将是 SpanTermQuery 或有序的零 slop SpanNearQuery,具体取决于发出的标记数量。最终效果是主查询始终以类似于标准 Lucene 解析器中的短语查询的方式运行(因此忽略 q.op 的任何值)。

如果将字段分析应用于查询,如果它改变了标记数,则标记的最终数必须与 payloads 参数中提供的有效负载数匹配。如果查询标记数与此查询提供的有效负载值数不匹配,则查询将不匹配。

此解析器接受以下参数

f

必需

默认值:无

要使用的字段。

有效负载

必需

默认值:无

要与文档中匹配标记中的有效负载进行比较的有效负载的空格分隔列表。在匹配之前,将使用根据字段类型确定的编码器对每个指定的有效负载进行编码。支持整数、浮点数和标识(字符串)编码,其含义与 DelimitedPayloadTokenFilter 相同。

op

可选

默认值:eq

要应用于有效负载检查的不等式运算。所有运算都要求从查询分析派生的连续标记匹配文档中的连续标记,此外,文档标记上的有效负载必须:* eq:等于指定的有效负载* gt:大于指定的有效负载* lt:小于指定的有效负载* gte:大于或等于指定的有效负载* lte:小于或等于指定的有效负载

示例

查找包含短语“searching stuff”的所有文档,其中 searching 的有效负载为“VERB”,而“stuff”的有效负载为“NOUN”

{!payload_check f=words_dps payloads="VERB NOUN"}searching stuff

查找所有包含“foo”的文档,其中“foo”的有效负载值大于或等于 0.75

{!payload_check f=words_dpf payloads="0.75" op="gte"}foo

查找包含短语“foo bar”的所有文档,其中术语“foo”的有效负载大于 9,而“bar”的有效负载大于 5

{!payload_check f=words_dpi payloads="9 5" op="gt"}foo bar

前缀查询解析器

PrefixQParser 通过从输入值创建前缀查询来扩展 QParserPlugin。目前,没有执行任何分析或值转换来创建此前缀查询。

参数是 f,即字段。前缀声明后的字符串被视为通配符查询。

示例

{!prefix f=myfield}foo

这通常等效于 Lucene 查询解析器表达式 myfield:foo*

原始查询解析器

RawQParser 通过从输入值创建术语查询来扩展 QParserPlugin,而无需任何文本分析或转换。这在调试时或从术语组件返回原始术语时很有用(这不是默认值)。

唯一的参数是 f,它定义要搜索的字段。

示例

{!raw f=myfield}Foo Bar

此示例构造查询:TermQuery(Term("myfield","Foo Bar"))

为了轻松构造筛选器以深入了解分面,建议使用 TermQParserPlugin

对于所有字段(包括文本字段)的完整分析,您可能希望使用 FieldQParserPlugin

排名查询解析器

RankQParserPluginFunctionQParser 的排名相关功能的更快速实现,并且可以与 RankFields 类型的专用字段一起使用。

它允许以下查询

http://localhost:8983/solr/techproducts?q=memory _query_:{!rank f='pagerank', function='log' scalingFactor='1.2'}

重新排名查询解析器

ReRankQParserPlugin 是一个特殊用途解析器,用于使用更复杂的排名查询对简单查询的顶部结果进行重新排名。

有关使用 ReRankQParserPlugin 的详细信息,请参阅 查询重新排名 部分。

简单查询解析器

Solr 中的简单查询解析器基于 Lucene 的 SimpleQueryParser。此查询解析器旨在允许用户以任何方式输入查询,并且它将尽力解释查询并返回结果。

此解析器采用以下参数

q.operators

可选

默认值:请参阅说明

要启用的解析运算符名称的逗号分隔列表。默认情况下,所有运算符都已启用,并且此参数可用于根据需要有效禁用特定运算符,方法是从列表中排除它们。使用此参数传递空字符串将禁用所有运算符。

名称 运算符 说明 示例查询

AND

+

指定 AND

token1+token2

OR

|

指定 OR

token1|token2

NOT

-

指定 NOT

-token3

PREFIX

*

指定前缀查询

term*

PHRASE

"

创建短语

"term1 term2"

PRECEDENCE

( )

指定优先级;括号内的令牌将首先进行分析。否则,正常的顺序是从左到右。

token1 + (token2 | token3)

ESCAPE

\

将其放在运算符前面以逐字匹配它们

C+\+

WHITESPACE

空格或 [\r\t\n]

在空格上定界令牌。如果未启用,则在分析之前不会执行空格拆分 - 通常最理想。

不拆分空格是此解析器的独特功能,它支持多词同义词。但是,除非将同义词配置为规范化而不是扩展到与给定的同义词匹配的所有内容,否则它可能实际上不起作用。此类配置要求在索引时间和查询时间规范化同义词。Solr 的分析屏幕在此处可以提供帮助。

term1 term2

FUZZY

~

~N

在术语末尾,指定模糊查询。

“N” 是可选的,可以是“1”或“2”(默认值)

term~1

NEAR

~N

在短语末尾,指定 NEAR 查询

“term1 term2”~5

q.op

可选

默认值:OR

定义如果用户未定义任何运算符,则使用的默认运算符。允许的值是ANDOR。如果未指定任何值,则使用OR

qf

可选

默认值:无

构建查询时要使用的查询字段和提升的列表。

df

可选

默认值:无

如果架构中未定义任何字段,则定义默认字段,或者如果已定义默认字段,则覆盖默认字段。

语法中的任何错误都将被忽略,查询解析器将尽其所能地解释查询。但是,在某些情况下,这会导致奇怪的结果。

空间查询解析器

Solr 中有两个空间 QParser:geofiltbbox。但是,还有其他方法可以进行空间查询:将 frange 解析器与距离函数一起使用,将标准(lucene)查询解析器与范围语法一起使用来选择矩形的角,或者使用 RPT 和 BBoxField,可以使用标准查询解析器,但使用引号内的特殊语法,允许您选择空间谓词。

所有这些选项都在 空间搜索 部分中进一步记录。

环绕查询解析器

SurroundQParser 启用环绕查询语法,该语法提供邻近搜索功能。有两个位置运算符:w 创建有序跨度查询,n 创建无序跨度查询。这两个运算符都采用一个数字值来表示两个术语之间的距离。默认值为1,最大值为99

请注意,查询字符串不会以任何方式进行分析。

示例

{!surround} 3w(foo, bar)

此示例查找术语“foo”和“bar”彼此相距不超过 3 个术语(即,它们之间不超过 2 个术语)的文档。

此查询解析器还接受布尔运算符(ANDORNOT,大小写均可)、通配符、短语搜索引号和提升。wn 运算符也可以用大写或小写表示。

非一元运算符(除 NOT 之外的所有运算符)支持前缀 (a AND b AND c) 和前缀 AND(a, b, c) 表示法。

切换查询解析器

SwitchQParser 是一个 QParserPlugin,它像“switch”或“case”语句一样工作。

主输入字符串会被修剪,然后加上前缀 case.,用作在解析器的本地参数中查找“switch case”的键。如果找到匹配的本地参数,则结果参数值将被解析为子查询,并作为解析结果返回。

case 本地参数可以被选择性地指定为一个 switch case,以匹配缺失(或空白)的输入字符串。default 本地参数可以被选择性地指定为一个默认 case,以在输入字符串不匹配任何其他 switch case 本地参数时使用。如果未指定 default,则任何不匹配 switch case 本地参数的输入都会导致语法错误。

在下面的示例中,每个查询的结果都是“XXX”

{!switch case.foo=XXX case.bar=zzz case.yak=qqq}foo
}bar 之间的额外空格会被自动修剪。
{!switch case.foo=qqq case.bar=XXX case.yak=zzz} bar
结果将回退到默认值。
{!switch case.foo=qqq case.bar=zzz default=XXX}asdf
没有输入使用 case 的值。
{!switch case=XXX case.bar=zzz case.yak=qqq}

此解析器的实际用法是在 SearchHandler 的配置中指定 appends 过滤器查询 (fq) 参数,以向使用自定义参数名称的客户端提供一组固定的过滤器选项。

使用下面的示例配置,客户端可以选择性地指定自定义参数 in_stockshipping 以覆盖默认的过滤行为,但仅限于特定的一组合法值(shipping=any|free,in_stock=yes|no|all)。

<requestHandler name="/select" class="solr.SearchHandler">
  <lst name="defaults">
    <str name="in_stock">yes</str>
    <str name="shipping">any</str>
  </lst>
  <lst name="appends">
    <str name="fq">{!switch case.all='*:*'
                            case.yes='inStock:true'
                            case.no='inStock:false'
                            v=$in_stock}</str>
    <str name="fq">{!switch case.any='*:*'
                            case.free='shipping_cost:0.0'
                            v=$shipping}</str>
  </lst>
</requestHandler>

词条查询解析器

TermQParser 通过从输入值创建等同于 readableToIndexed() 的单个词条查询来扩展 QParserPlugin。这对于从分面或词条组件返回的外部人类可读词条生成过滤器查询很有用。唯一的参数是 f,用于字段。

示例

{!term f=weight}1.5

对于文本字段,不进行分析,因为分面和词条组件已经返回了原始词条。要对文本字段也应用分析,请参见上面的 字段查询解析器

如果对任何类型的字段都不需要分析或转换,请参见上面的 原始查询解析器

词条查询解析器

TermsQParser 的功能类似于 Term Query Parser,但它采用以逗号分隔的多值,并返回与任何指定值匹配的文档。

这对于从分面或术语组件返回的人类可读外部术语生成筛选查询很有用,并且在某些情况下可能比使用 Standard Query Parser 生成布尔查询更有效,因为默认实现 method 避免评分。

此查询解析器采用以下参数

f

必需

默认值:无

要搜索的字段。

分隔符

可选

默认值:,(逗号)

解析输入时要使用的分隔符。如果设置为“ ”(单个空格),将从输入术语中修剪额外的空格。

方法

可选

默认值:termsFilter

确定 Solr 应使用哪些查询实现。

选项仅限于:termsFilterbooleanQueryautomatondocValuesTermsFilterPerSegmentdocValuesTermsFilterTopLeveldocValuesTermsFilter

每种实现都有其自身的性能特征,建议用户进行试验以确定哪种实现对他们的用例最有效。启发式方法如下。

booleanQuery 创建一个表示请求的 BooleanQuery。随着索引大小的增加而扩展良好,但随着要搜索的术语数量的增加而扩展不佳。

termsFilter 根据术语数量使用 BooleanQueryTermInSetQuery。随着索引大小的增加而扩展良好,但随着查询术语数量的增加而扩展一般。

docValuesTermsFilter 只能用于具有 docValues 数据的字段。默认情况下,cache 参数为 false。使用查询术语数量作为粗略启发式方法,在 docValuesTermsFilterTopLeveldocValuesTermsFilterPerSegment 方法之间进行选择。用户通常应使用此方法,而不是直接使用 docValuesTermsFilterTopLeveldocValuesTermsFilterPerSegment,除非他们已执行性能测试以验证所有大小的查询中的一种方法。根据所选的实现,此方法可能依赖于昂贵的数据结构,这些数据结构在每次提交后都会延迟填充。如果您经常提交并且您的用例可以容忍静态预热查询,请考虑将一个添加到 solrconfig.xml,以便将此工作作为提交本身的一部分完成,而不是直接附加到用户请求中。

docValuesTermsFilterTopLevel 只能用于具有 docValues 数据的字段。cache 参数默认值为 false。使用顶级 docValues 数据结构查找结果。随着查询词条数量的增加(超过几百个),这些数据结构会变得更有效。但是,它们构建起来也很昂贵,并且需要在每次提交后延迟填充,这会导致每次提交后的首次查询有时会明显变慢。如果您频繁提交,并且您的用例可以容忍静态预热查询,请考虑将一个添加到 solrconfig.xml 中,以便这项工作作为提交本身的一部分完成,而不是直接附加到用户请求上。

docValuesTermsFilterPerSegment 只能用于具有 docValues 数据的字段。cache 参数默认值为 false。对于查询词条数量较少到中等(~500)的情况,它比“顶级”替代方案更有效,并且不会在提交后立即进行的查询中变慢(如 docValuesTermsFilterTopLevel 所做的那样 - 见上文)。但对于数量非常大的查询词条,它的性能较低。

automaton 创建一个 AutomatonQuery,表示每个词条形成并集的请求。随着索引大小和查询词条数量的适度增加而扩展良好。

示例

{!terms f=tags}software,apache,solr,lucene
{!terms f=categoryId method=booleanQuery separator=" "}8 6 7 5309

XML 查询解析器

XmlQParserPlugin 扩展了 QParserPlugin,并支持从 XML 创建查询。示例

参数

defType

xmlparser

q

<BooleanQuery fieldName="description">
   <Clause occurs="must">
      <TermQuery>shirt</TermQuery>
   </Clause>
   <Clause occurs="mustnot">
      <TermQuery>plain</TermQuery>
   </Clause>
   <Clause occurs="should">
      <TermQuery>cotton</TermQuery>
   </Clause>
   <Clause occurs="must">
      <BooleanQuery fieldName="size">
         <Clause occurs="should">
            <TermsQuery>S M L</TermsQuery>
         </Clause>
      </BooleanQuery>
   </Clause>
</BooleanQuery>

XmlQParser 实现使用 SolrCoreParser 类,该类扩展了 Lucene 的 CoreParser 类。XML 元素映射到 QueryBuilder 类,如下所示

XML 元素 QueryBuilder 类

<BooleanQuery>

BooleanQueryBuilder

<BoostingTermQuery>

BoostingTermBuilder

<ConstantScoreQuery>

ConstantScoreQueryBuilder

<DisjunctionMaxQuery>

DisjunctionMaxQueryBuilder

<MatchAllDocsQuery>

MatchAllDocsQueryBuilder

<RangeQuery>

RangeQueryBuilder

<SpanFirst>

SpanFirstBuilder

<SpanPositionRange>

SpanPositionRangeBuilder

<SpanNear>

SpanNearBuilder

<SpanNot>

SpanNotBuilder

<SpanOr>

SpanOrBuilder

<SpanOrTerms>

SpanOrTermsBuilder

<SpanTerm>

SpanTermBuilder

<TermQuery>

TermQueryBuilder

<TermsQuery>

TermsQueryBuilder

<UserQuery>

UserInputQueryBuilder

<LegacyNumericRangeQuery>

LegacyNumericRangeQuery(Builder) 已弃用

自定义 XML 查询解析器

您可以为其他 XML 元素配置您自己的自定义查询构建器。自定义构建器需要扩展 SolrQueryBuilderSolrSpanQueryBuilder 类。示例 solrconfig.xml 代码段

<queryParser name="xmlparser" class="XmlQParserPlugin">
  <str name="MyCustomQuery">com.mycompany.solr.search.MyCustomQueryBuilder</str>
</queryParser>