Solr查询:建议器功能详解

Solr查询:建议器功能详解

概述

Solr中的SuggestComponent为用户提供查询词的自动建议功能。

您可以使用它在搜索应用程序中实现强大的自动建议功能。

虽然可以使用拼写检查功能来支持自动建议行为,但Solr有专门为此功能设计的SuggestComponent。

这种方法利用Lucene的Suggester实现,支持Lucene中所有可用的查找实现。

此建议器的主要功能包括:

  • 查找实现可插拔性
  • 词典实现可插拔性,为您选择字典实现提供灵活性
  • 分布式支持

Solr”techproducts”示例中的solrconfig.xml已经配置了建议器实现。有关搜索组件的更多信息,请参阅请求处理器和搜索组件部分。

“techproducts”示例solrconfig.xml已经配置了suggest搜索组件和/suggest请求处理器。您可以将其作为配置的基础,或从头创建,如下详述。

添加建议搜索组件

第一步是在solrconfig.xml中添加搜索组件并告诉它使用SuggestComponent。以下是一些可以使用的示例代码。

1
2
3
4
5
6
7
8
9
10
11
<searchComponent name="suggest" class="solr.SuggestComponent">
<lst name="suggester">
<str name="name">mySuggester</str>
<str name="lookupImpl">FuzzyLookupFactory</str>
<str name="dictionaryImpl">DocumentDictionaryFactory</str>
<str name="field">cat</str>
<str name="weightField">price</str>
<str name="suggestAnalyzerFieldType">string</str>
<str name="buildOnStartup">false</str>
</lst>
</searchComponent>

建议器搜索组件参数

建议器搜索组件需要几个配置参数。

查找实现(lookupImpl,如何在建议字典中找到术语)和字典实现(dictionaryImpl,如何在建议字典中存储术语)的选择将决定所需的一些参数。

以下是无论使用什么查找或字典实现都可以使用的主要参数。在后面的部分中,为每个实现提供了额外的参数。

searchComponent name

  • 必需,默认:无
  • 整个搜索组件定义的任意名称

searchComponent class

  • 必需,默认:无
  • 建议器类。应定义为solr.SuggestComponent

name

  • 必需,默认:无
  • 此建议器的符号名称。您可以在URL参数和SearchHandler配置中引用此名称。在一个solrconfig.xml文件中可以有多个这样的名称

lookupImpl

  • 可选,默认:JaspellLookupFactory
  • 查找实现。有几种可能的实现,在”查找实现”部分中描述

dictionaryImpl

  • 可选,默认:见描述
  • 要使用的字典实现。有几种可能的实现,在”字典实现”部分中描述
  • 如果未设置,默认字典实现为HighFrequencyDictionaryFactory。但是,如果使用sourceLocation,字典实现将是FileDictionaryFactory

field

  • 可选,默认:无
  • 索引中用作建议术语基础的字段。如果sourceLocation为空(意味着除FileDictionaryFactory之外的任何字典实现),则将使用索引中此字段的术语
  • 要用作建议的基础,字段必须是存储的。您可能希望使用copyField规则创建一个由文档中其他字段术语组成的特殊’suggest’字段
  • 您通常希望对字段进行最少的分析(无词干提取,无同义词等),因此一个选项是在模式中创建仅使用基本分词器或过滤器的字段类型。这样的字段类型示例如下:
1
2
3
4
5
6
<fieldType class="solr.TextField" name="textSuggest" positionIncrementGap="100">
<analyzer>
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>

但是,如果您希望对术语进行更多分析,则不需要这种最小分析。

但是,如果使用AnalyzingLookupFactory作为您的lookupImpl,您可以选择定义用于索引和查询时分析的字段类型规则。

sourceLocation

  • 可选,默认:见描述
  • 如果使用FileDictionaryFactory,字典文件的路径。如果此值为空,主索引将用作术语和权重的来源

storeDir

  • 可选,默认:无
  • 存储字典文件的位置

buildOnCommit和buildOnOptimize

  • 可选,默认:false
  • 如果为true,查找数据结构将在软提交后重建。如果为false,则仅当URL参数suggest.build=true请求时才会构建查找数据
  • 使用buildOnCommit在每次软提交时重建字典,或使用buildOnOptimize仅在索引优化时构建字典
  • 某些查找实现可能需要很长时间来构建,特别是对于大型索引。在这种情况下,不建议使用buildOnCommitbuildOnOptimize,特别是在软提交频率很高的情况下。相反,通过手动发出带有suggest.build=true的请求以较低频率构建建议器

buildOnStartup

  • 可选,默认:false
  • 如果为true,则在Solr启动或核心重新加载时将构建查找数据结构。如果未指定此参数,建议器将检查查找数据结构是否存在于磁盘上,如果未找到则构建它
  • 将此设置为true可能导致Solr加载(或重新加载)核心时间更长,因为构建建议器数据结构有时可能需要很长时间。通常最好将此设置为false,并使用suggest.build=true手动构建建议器

查找实现

lookupImpl参数定义用于在建议索引中查找术语的算法。有几种可能的实现可供选择,有些需要配置额外的参数。

AnalyzingLookupFactory

首先分析输入文本并将分析形式添加到加权FST的查找,然后在查找时执行相同的操作。

此实现使用以下附加属性:

suggestAnalyzerFieldType

  • 必需,默认:无
  • 用于查询时和构建时术语建议分析的字段类型

exactMatchFirst

  • 可选,默认:true
  • 如果为true,首先返回精确建议,即使它们是前缀或FST中的其他字符串具有更大的权重

preserveSep

  • 可选,默认:true
  • 如果为true,则保留标记之间的分隔符。这意味着建议对分词敏感(例如,baseball与base ball不同)

preservePositionIncrements

  • 可选,默认:false
  • 如果为true,建议器将保留位置增量。这意味着留下间隙的标记过滤器(例如,当StopFilter匹配停用词时)在构建建议器时会尊重位置

FuzzyLookupFactory

这是AnalyzingSuggester的扩展但本质上是模糊的建议器。相似性由Levenshtein算法衡量。

此实现使用以下附加属性:

exactMatchFirst

  • 可选,默认:true
  • 如果为true,首先返回精确建议,即使它们是前缀或FST中的其他字符串具有更大的权重

preserveSep

  • 可选,默认:true
  • 如果为true,则保留标记之间的分隔符。这意味着建议对分词敏感(例如,”baseball”与”base ball”不同)

maxSurfaceFormsPerAnalyzedForm

  • 可选,默认:256
  • 为单个分析形式保留的表面形式的最大数量。当表面形式太多时,我们丢弃权重最低的那些

maxGraphExpansions

  • 可选,默认:-1
  • 在构建FST(”索引时”)时,我们将每个通过分词流图的路径作为单独的条目添加。这对单个建议将添加多少扩展设置了上限

preservePositionIncrements

  • 可选,默认:false
  • 如果为true,建议器将保留位置增量。这意味着留下间隙的标记过滤器(例如,当StopFilter匹配停用词时)在构建建议器时会尊重位置

maxEdits

  • 可选,默认:1
  • 允许的最大字符串编辑数。Solr的硬限制是2

transpositions

  • 可选,默认:true
  • 如果为true,转置应被视为原始编辑操作

nonFuzzyPrefix

  • 可选,默认:1
  • 必须匹配建议的公共非模糊前缀匹配的长度

minFuzzyLength

  • 可选,默认:3
  • 允许任何字符串编辑之前查询的最小长度

unicodeAware

  • 可选,默认:false
  • 如果为truemaxEditsminFuzzyLengthtranspositionsnonFuzzyPrefix参数将以unicode代码点(实际字母)而不是字节来衡量

AnalyzingInfixLookupFactory

分析输入文本,然后根据对索引文本中任何标记的前缀匹配建议匹配。这使用Lucene索引作为其字典。

此实现使用以下附加属性:

indexPath

  • 可选,默认:见描述
  • 使用AnalyzingInfixSuggester时,您可以提供将构建索引的自己的路径。默认值为analyzingInfixSuggesterIndexDir,将在您的集合的data/目录中创建

minPrefixChars

  • 可选,默认:4
  • 使用PrefixQuery之前的最小前导字符数。短于此的前缀被索引为字符ngrams(增加索引大小但使查找更快)

allTermsRequired

  • 可选,默认:true
  • 如果为true,将需要所有术语

highlight

  • 可选,默认:true
  • 高亮显示建议术语

此实现支持上下文过滤。

BlendedInfixLookupFactory

AnalyzingInfixSuggester的扩展,提供额外功能来权衡匹配文档中的前缀匹配。如果命中更接近建议的开始,它会得分更高。

此实现使用以下附加属性:

blenderType

  • 可选,默认:position_linear
  • 用于使用第一个匹配词的位置计算权重系数。可用选项有:
  • position_linear:开始的匹配将获得更高分数
    weightFieldValue * (1 - 0.10*position)

  • position_reciprocal:开始的匹配将获得更高分数。远离建议开始位置的匹配分数衰减比线性更快
    weightFieldValue / (1 + position)

  • position_exponential_reciprocal:开始的匹配将获得更高分数。远离建议开始位置的匹配分数衰减比倒数更快
    weightFieldValue / pow(1 + position,exponent)

使用此blender类型时,有一个额外参数可用:
** exponent:控制分数下降的速度。默认2.0

numFactor

  • 可选,默认:10
  • 将从中修剪结果的搜索元素数量的乘数因子

indexPath

  • 可选,默认:见描述
  • 使用BlendedInfixSuggester时,您可以提供将构建索引的自己的路径。默认目录名为blendedInfixSuggesterIndexDir,将在您的集合数据目录中创建

minPrefixChars

  • 可选,默认:4
  • 使用PrefixQuery之前的最小前导字符数。短于此的前缀被索引为字符ngrams,这增加了索引大小但使查找更快

此实现支持上下文过滤。

FreeTextLookupFactory

它查看最后的标记以及用户正在输入的任何最终标记的前缀(如果存在)来预测最可能的下一个标记。还可以指定需要考虑的先前标记数。此建议器仅在主建议器找不到任何建议时用作后备。

此实现使用以下附加属性:

suggestFreeTextAnalyzerFieldType

  • 必需,默认:无
  • 在”查询时”和”构建时”用于分析建议的字段类型

ngrams

  • 可选,默认:2
  • 将从中制作字典的单个标记的最大数量。增加这意味着您希望在提出建议时考虑超过前2个标记

FSTLookupFactory

基于自动机的查找。此实现构建较慢,但提供最低的内存成本。我们建议使用此实现,除非您需要更复杂的匹配结果,在这种情况下应该使用Jaspell实现。

此实现使用以下附加属性:

exactMatchFirst

  • 可选,默认:true
  • 如果为true(默认值),首先返回精确建议,即使它们是前缀或FST中的其他字符串具有更大的权重

weightBuckets

  • 可选,默认:无
  • 建议器在构建其字典时将使用的权重的单独桶数

TSTLookupFactory

基于简单紧凑三元树的查找。

WFSTLookupFactory

加权自动机表示,是用于更细粒度排名的FSTLookup的替代方案。WFSTLookup不使用桶,而是使用最短路径算法。

注意它期望权重为整数。如果权重丢失,假定为1.0。当选择spellcheck.onlyMorePopular=true时,权重影响匹配建议的排序:权重被视为”受欢迎程度”分数,更高权重比较低权重的建议更受欢迎。

JaspellLookupFactory

基于JaSpell项目中三元树的更复杂查找。如果您需要更复杂的匹配结果,请使用此实现。

字典实现

字典实现定义术语如何存储。有几个选项,如果需要,可以在单个请求中使用多个字典。

DocumentDictionaryFactory

具有从索引中获取的术语、权重和可选负载的字典。

此字典实现除了建议器通常描述的参数和查找实现的参数外,还采用以下参数:

weightField

  • 可选,默认:无
  • 存储的字段或数值DocValue字段

payloadField

  • 可选,默认:无
  • payloadField应该是存储的字段

contextField

  • 可选,默认:无
  • 用于上下文过滤的字段。请注意,只有某些查找实现支持过滤

DocumentExpressionDictionaryFactory

此字典实现与DocumentDictionaryFactory相同,但允许用户在weightExpression标签中指定任意表达式。

此字典实现除了建议器通常描述的参数和查找实现的参数外,还采用以下参数:

payloadField

  • 可选,默认:无
  • payloadField应该是存储的字段

weightExpression

  • 必需,默认:无
  • 用于为建议评分的任意表达式。使用的字段必须是数值字段

contextField

  • 可选,默认:无
  • 用于上下文过滤的字段。请注意,只有某些查找实现支持过滤

HighFrequencyDictionaryFactory

此字典实现允许添加阈值来修剪非常常见的术语可能压倒其他术语的情况下的不太频繁的术语。

此字典实现除了建议器通常描述的参数和查找实现的参数外,还采用一个参数:

threshold

  • 可选,默认:0
  • 0到1之间的值,表示术语为了添加到查找字典中应该出现在总文档中的最小分数

FileDictionaryFactory

此字典实现允许使用包含建议条目的外部文件。也可以使用权重和负载。

如果使用字典文件,它应该是UTF-8编码的纯文本文件。您可以在字典文件中使用单个术语和短语。如果添加权重或负载,那些应该使用fieldDelimiter属性定义的分隔符与术语分开(默认是\t,制表符表示)。如果使用负载,文件中的第一行必须指定负载。

此字典实现除了建议器通常描述的参数和查找实现的参数外,还采用一个参数:

fieldDelimiter

  • 可选,默认:\t
  • 指定用于分隔条目、权重和负载的分隔符。默认是制表符(\t

示例文件:

1
2
3
acquire
accidentally 2.0
accommodate 3.0

多个字典

可以在单个SuggestComponent定义中包含多个dictionaryImpl定义。

要做到这一点,只需定义单独的建议器,如此示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<searchComponent name="suggest" class="solr.SuggestComponent">
<lst name="suggester">
<str name="name">mySuggester</str>
<str name="lookupImpl">FuzzyLookupFactory</str>
<str name="dictionaryImpl">DocumentDictionaryFactory</str>
<str name="field">cat</str>
<str name="weightField">price</str>
<str name="suggestAnalyzerFieldType">string</str>
</lst>
<lst name="suggester">
<str name="name">altSuggester</str>
<str name="dictionaryImpl">DocumentExpressionDictionaryFactory</str>
<str name="lookupImpl">FuzzyLookupFactory</str>
<str name="field">product_name</str>
<str name="weightExpression">((price * 2) + ln(popularity))</str>
<str name="sortField">weight</str>
<str name="sortField">price</str>
<str name="storeDir">suggest_fuzzy_doc_expr_dict</str>
<str name="suggestAnalyzerFieldType">text_en</str>
</lst>
</searchComponent>

在查询中使用这些建议器时,您将在请求中定义多个suggest.dictionary参数,引用搜索组件定义中每个建议器给定的名称。响应将在每个建议器的部分中包含术语。

添加建议请求处理器

添加搜索组件后,必须在solrconfig.xml中添加请求处理器。此请求处理器的工作方式与任何其他请求处理器相同,允许您配置用于服务建议请求的默认参数。请求处理器定义必须包含先前定义的”suggest”搜索组件。

1
2
3
4
5
6
7
8
9
<requestHandler name="/suggest" class="solr.SearchHandler" startup="lazy">
<lst name="defaults">
<str name="suggest">true</str>
<str name="suggest.count">10</str>
</lst>
<arr name="components">
<str>suggest</str>
</arr>
</requestHandler>

建议请求处理器参数

以下参数允许您为建议请求处理器设置默认值:

suggest

  • 可选,默认:false
  • 此参数应始终为true,因为我们始终希望为提交给此处理器的查询运行建议器

suggest.dictionary

  • 必需,默认:无
  • 在搜索组件中配置的字典组件的名称。可以在请求处理器中设置,或在查询时作为参数发送

suggest.q

  • 可选,默认:无
  • 用于建议查找的查询。如果未提供,使用q参数

suggest.count

  • 可选,默认:1
  • 指定Solr返回的建议数量

suggest.cfq

  • 可选,默认:无
  • 如果建议器支持,用于根据上下文字段过滤建议的上下文过滤查询
  • 目前只有AnalyzingInfixLookupFactoryBlendedInfixLookupFactory支持上下文过滤,并且只有当由Document*Dictionary支持时。所有其他实现将返回未过滤的匹配,就像没有请求过滤一样

suggest.build

  • 可选,默认:false
  • 如果为true,将构建建议器索引。这可能仅对初始请求有用;您可能不希望在每个请求上构建字典,特别是在生产系统中。如果您希望保持字典更新,应该为搜索组件使用buildOnCommitbuildOnOptimize参数

suggest.reload

  • 可选,默认:false
  • 如果为true,将重新加载建议器索引

suggest.buildAll

  • 可选,默认:false
  • 如果为true,将构建所有建议器索引

suggest.reloadAll

  • 可选,默认:false
  • 如果为true,将重新加载所有建议器索引

这些属性也可以在查询时覆盖,或完全不在请求处理器中设置而始终在查询时发送。

使用示例

获取带权重的建议

这是使用单个字典和单个Solr核心的基本建议。

示例查询:

1
http://localhost:8983/solr/techproducts/suggest?suggest=true&suggest.build=true&suggest.dictionary=mySuggester&suggest.q=elec

在此示例中,我们简单地使用suggest.q参数请求字符串’elec’,并请求使用suggest.build构建建议字典(但请注意,您可能不希望在每个查询上构建索引——相反,如果您有定期更改的文档,应该使用buildOnCommitbuildOnOptimize)。

示例响应:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
{
"responseHeader": {
"status": 0,
"QTime": 35
},
"command": "build",
"suggest": {
"mySuggester": {
"elec": {
"numFound": 3,
"suggestions": [
{
"term": "electronics and computer1",
"weight": 2199,
"payload": ""
},
{
"term": "electronics",
"weight": 649,
"payload": ""
},
{
"term": "electronics and stuff2",
"weight": 279,
"payload": ""
}
]
}
}
}
}

使用多个字典

如果您定义了多个字典,可以在查询中使用它们。

示例查询:

1
http://localhost:8983/solr/techproducts/suggest?suggest=true&suggest.dictionary=mySuggester&suggest.dictionary=altSuggester&suggest.q=elec

在此示例中,我们将字符串’elec’作为suggest.q参数发送,并命名了两个要使用的suggest.dictionary定义。

示例响应:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{
"responseHeader": {
"status": 0,
"QTime": 3
},
"suggest": {
"mySuggester": {
"elec": {
"numFound": 1,
"suggestions": [
{
"term": "electronics and computer1",
"weight": 100,
"payload": ""
}
]
}
},
"altSuggester": {
"elec": {
"numFound": 1,
"suggestions": [
{
"term": "electronics and computer1",
"weight": 10,
"payload": ""
}
]
}
}
}
}

上下文过滤

上下文过滤让您根据单独的上下文字段(如类别、部门或任何其他标记)过滤建议。AnalyzingInfixLookupFactoryBlendedInfixLookupFactory目前支持此功能,当由DocumentDictionaryFactory支持时。

在建议器配置中添加contextField。此示例将建议名称并允许按类别过滤:

1
2
3
4
5
6
7
8
9
10
11
12
<searchComponent name="suggest" class="solr.SuggestComponent">
<lst name="suggester">
<str name="name">mySuggester</str>
<str name="lookupImpl">AnalyzingInfixLookupFactory</str>
<str name="dictionaryImpl">DocumentDictionaryFactory</str>
<str name="field">name</str>
<str name="weightField">price</str>
<str name="contextField">cat</str>
<str name="suggestAnalyzerFieldType">string</str>
<str name="buildOnStartup">false</str>
</lst>
</searchComponent>

示例上下文过滤建议查询:

1
http://localhost:8983/solr/techproducts/suggest?suggest=true&suggest.build=true&suggest.dictionary=mySuggester&suggest.q=c&suggest.cfq=memory

建议器将仅返回标记为’cat=memory’的产品建议。


本文档翻译自Apache Solr官方参考指南,旨在为中文用户提供完整的建议器功能使用指南。

© 2025 Solr Community of China All Rights Reserved. 本站访客数人次 本站总访问量
Theme by hiero