建议器
Solr 中的 SuggestComponent 为用户提供查询字词的自动建议。
你可以使用此功能在搜索应用程序中实现强大的自动建议功能。
虽然可以使用 拼写检查 功能来实现自动建议行为,但 Solr 有一个专用的 SuggestComponent,专为此功能而设计。
此方法利用了 Lucene 的 Suggester 实现,并支持 Lucene 中提供的所有查找实现。
此 Suggester 的主要功能是
-
查找实现可插拔性
-
术语词典可插拔性,让你可以灵活地选择词典实现
-
分布式支持
Solr 的“techproducts”示例中找到的 solrconfig.xml
已经配置了 Suggester 实现。有关搜索组件的更多信息,请参阅部分 请求处理程序和搜索组件。
“techproducts”示例 solrconfig.xml
已经配置了 suggest
搜索组件和 /suggest
请求处理程序。你可以将其用作配置的基础,或从头开始创建,如下所述。
添加 Suggest 搜索组件
第一步是向 solrconfig.xml
添加一个搜索组件,并告诉它使用 SuggestComponent。这里有一些可以使用的示例代码。
<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>
Suggester 搜索组件参数
Suggester 搜索组件采用多个配置参数。
查找实现(lookupImpl
,如何在建议词典中找到术语)和词典实现(dictionaryImpl
,如何在建议词典中存储术语)的选择将决定所需的一些参数。
无论使用什么查找或词典实现,都可以使用以下主要参数。在以下部分中,为每个实现提供了其他参数。
searchComponent 名称
-
必需
默认值:无
整个搜索组件定义的任意名称。
searchComponent 类
-
必需
默认值:无
Suggester 类。这应定义为
solr.SuggestComponent
。 名称
-
必需
默认值:无
此建议者的符号名称。您可以在 URL 参数和 SearchHandler 配置中引用此名称。在一个
solrconfig.xml
文件中可以有多个此名称。在上面的示例配置中,这是在以下行中引用的名称:<str name="name">mySuggester</str>
。 lookupImpl
-
可选
默认值:
JaspellLookupFactory
查找实现。有几种可能的实现,如 查找实现 部分所述。
dictionaryImpl
-
可选
默认值:参见说明
要使用的词典实现。有几种可能的实现,如 词典实现 部分所述。
如果未设置,则默认词典实现为
HighFrequencyDictionaryFactory
。但是,如果使用sourceLocation
,则词典实现将为FileDictionaryFactory
。 字段
-
可选
默认值:无
从索引中用作建议术语基础的字段。如果
sourceLocation
为空(表示除FileDictionaryFactory
之外的任何词典实现),则将使用索引中此字段中的术语。要作为建议的基础,该字段必须存储。您可能希望 使用 copyField 规则 创建一个特殊的“建议”字段,其中包含文档中其他字段的术语。
您通常希望对该字段进行最少的分析(不进行词干提取、不使用同义词等),因此一种选择是在架构中创建一个仅使用基本分词器或过滤器的字段类型。此类字段类型的示例如下所示
<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
仅在优化索引时构建词典。某些查找实现可能需要很长时间才能构建,尤其是在索引较大的情况下。在这种情况下,不建议使用
buildOnCommit
或buildOnOptimize
,尤其是当软提交的频率很高时。相反,通过手动发出带有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
。 转置
-
可选
默认值:
true
如果为
true
,则应将转置视为原始编辑操作。 nonFuzzyPrefix
-
可选
默认值:
1
必须与建议匹配的公共非模糊前缀匹配的长度。
minFuzzyLength
-
可选
默认值:
3
允许任何字符串编辑操作之前的查询的最小长度。
unicodeAware
-
可选
默认值:
false
如果为
true
,则maxEdits
、minFuzzyLength
、transpositions
和nonFuzzyPrefix
参数将以 Unicode 代码点(实际字母)而不是字节为单位进行测量。
AnalyzingInfixLookupFactory
分析输入文本,然后根据索引文本中任何标记的前缀匹配建议匹配项。这使用 Lucene 索引作为其词典。
此实现使用以下附加属性。
indexPath
-
可选
默认值:参见说明
当使用
AnalyzingInfixSuggester
时,你可以提供自己的路径,索引将在其中构建。默认值为analyzingInfixSuggesterIndexDir
,它将在集合的data/
目录中创建。 minPrefixChars
-
可选
默认值:
4
使用 PrefixQuery 之前的最小前导字符数。小于此值的词干将被编入字符 n 元语法(增加索引大小,但加快查找速度)。
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)
使用此混合器类型时,可以使用一个附加参数
-
exponent
:控制分数下降的速度。默认值为2.0
。
-
-
numFactor
-
可选
默认值:
10
用于乘以将修剪结果从中搜索到的元素数量的因子。
indexPath
-
可选
默认值:参见说明
使用
BlendedInfixSuggester
时,您可以提供索引将构建到的自己的路径。默认目录名称为blendedInfixSuggesterIndexDir
,将在您的集合数据目录中创建。 minPrefixChars
-
可选
默认值:
4
使用 PrefixQuery 之前的最小领先字符数。小于此值的词缀将作为字符 ngram 索引,这会增加索引大小,但会加快查找速度。
此实现支持 上下文筛选。
FreeTextLookupFactory
它查看最后一个标记,以及用户正在键入的最后一个标记的前缀(如果存在),以预测最可能的下一个标记。还可以指定需要考虑的前一个标记的数量。此建议者仅用作后备,当主建议者无法找到任何建议时。
此实现使用以下附加属性
suggestFreeTextAnalyzerFieldType
-
必需
默认值:无
在“查询时间”和“构建时间”用于分析建议的字段类型。
ngrams
-
可选
默认值:
2
从其中创建词典的标记的最大数量。增加此值意味着您希望在提出建议时考虑前 2 个以上的标记。
FSTLookupFactory
基于自动机的查找。此实现的构建速度较慢,但提供的内存成本最低。我们建议使用此实现,除非您需要更复杂的匹配结果,在这种情况下,您应该使用 Jaspell 实现。
此实现使用以下附加属性
exactMatchFirst
-
可选
默认值:
true
如果为
true
(默认值),则首先返回精确建议,即使它们是前缀或 FST 中的其他字符串具有更大的权重。 weightBuckets
-
可选
默认值:无
建议者在构建其词典时将使用的权重的单独存储桶的数量。
WFSTLookupFactory
加权自动机表示,它是 FSTLookup
的替代方案,用于更细粒度的排名。WFSTLookup
不使用存储桶,而是使用最短路径算法。
请注意,它期望权重为整数。如果缺少权重,则假定为 1.0
。当选择 spellcheck.onlyMorePopular=true
时,权重会影响匹配建议的排序:权重被视为“流行度”分数,权重较高的建议优先于权重较低的建议。
JaspellLookupFactory
基于来自 JaSpell 项目的三元树的更复杂的查找。如果您需要更复杂的匹配结果,请使用此实现。
词典实现
词典实现定义了术语的存储方式。有多种选项,并且在必要时可以在单个请求中使用多个词典。
DocumentDictionaryFactory
包含从索引中获取的术语、权重和可选有效负载的词典。
除了针对 Suggester 以及查找实现描述的参数外,此词典实现还采用以下参数
weightField
-
可选
默认值:无
已存储的字段或数字 DocValue 字段。
payloadField
-
可选
默认值:无
payloadField
应为已存储的字段。 contextField
-
可选
默认值:无
用于 上下文筛选 的字段。请注意,只有部分查找实现支持筛选。
DocumentExpressionDictionaryFactory
此词典实现与 DocumentDictionaryFactory
相同,但允许用户在 weightExpression
标记中指定任意表达式。
除了针对 Suggester 以及查找实现描述的参数外,此词典实现还采用以下参数
payloadField
-
可选
默认值:无
payloadField
应为已存储的字段。 weightExpression
-
必需
默认值:无
用于对建议进行评分的任意表达式。所使用的字段必须为数字字段。
contextField
-
可选
默认值:无
用于 上下文筛选 的字段。请注意,只有部分查找实现支持筛选。
HighFrequencyDictionaryFactory
此词典实现允许添加阈值,以便在非常常见的术语可能淹没其他术语的情况下剔除频率较低的术语。
除了针对 Suggester 以及查找实现描述的参数外,此词典实现还采用一个参数
threshold
-
可选
默认值:
0
介于
0
和1
之间的值,表示术语应出现在总文档中的最小分数,才能添加到查找词典中。
FileDictionaryFactory
此词典实现允许使用包含建议项的外部文件。还可以使用权重和有效负载。
如果使用词典文件,则它应为 UTF-8 编码的纯文本文件。你可以在词典文件中同时使用单个术语和短语。如果添加权重或有效负载,则应使用 fieldDelimiter
属性定义的分隔符将它们与术语分隔(默认值为 \t
,即制表符表示)。如果使用有效负载,则文件中的第一行必须指定有效负载。
除了针对 Suggester 以及查找实现描述的参数外,此词典实现还采用一个参数
fieldDelimiter
-
可选
默认值:
\t
指定用于分隔项、权重和有效负载的分隔符。默认值为制表符 (
\t
)。示例文件acquire accidentally 2.0 accommodate 3.0
多个词典
可以在单个 SuggestComponent 定义中包含多个 dictionaryImpl
定义。
为此,只需定义单独的建议者,如下例所示
<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”搜索组件。
<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
-
可选
默认值:无
如果建议器支持,则用于根据上下文字段过滤建议的 上下文筛选器 查询。
目前,只有
AnalyzingInfixLookupFactory
和BlendedInfixLookupFactory
支持上下文筛选,并且仅当由Document*Dictionary
支持时才支持。所有其他实现都将返回未筛选的匹配项,就像未请求筛选一样。 suggest.build
-
可选
默认值:
false
如果为
true
,它将构建建议器索引。这可能仅对初始请求有用;您可能不想在每个请求上构建词典,尤其是在生产系统中。如果您希望保持词典是最新的,则应为搜索组件使用buildOnCommit
或buildOnOptimize
参数。 suggest.reload
-
可选
默认值:
false
如果为
true
,则将重新加载建议索引。 suggest.buildAll
-
可选
默认值:
false
如果为
true
,则将构建所有建议索引。 suggest.reloadAll
-
可选
默认值:
false
如果为
true
,则将重新加载所有建议索引。
这些属性也可以在查询时覆盖,或者根本不在请求处理程序中设置,而始终在查询时发送。
示例用法
获取带权重的建议
这是一个使用单个词典和单个 Solr 核心的基本建议。
示例查询
http://localhost:8983/solr/techproducts/suggest?suggest=true&suggest.build=true&suggest.dictionary=mySuggester&suggest.q=elec
在此示例中,我们使用 suggest.q
参数简单地请求了字符串“elec”,并请求使用 suggest.build
构建建议词典(但请注意,您可能不想在每次查询时都构建索引 - 如果您的文档经常更改,则应该使用 buildOnCommit
或 buildOnOptimize
)。
示例响应
{
"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": ""
}
]
}
}
}
}
使用多个词典
如果您定义了多个词典,则可以在查询中使用它们。
示例查询
http://localhost:8983/solr/techproducts/suggest?suggest=true&suggest.dictionary=mySuggester&suggest.dictionary=altSuggester&suggest.q=elec
在此示例中,我们已将字符串“elec”作为 suggest.q
参数发送,并指定了要使用的两个 suggest.dictionary
定义。
示例响应
{
"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": ""
}
]
}
}
}
}
上下文筛选
上下文筛选允许您按单独的上下文字段(例如类别、部门或任何其他标记)筛选建议。当由 DocumentDictionaryFactory
支持时,AnalyzingInfixLookupFactory
和 BlendedInfixLookupFactory
目前支持此功能。
将 contextField
添加到您的建议程序配置中。此示例将建议名称,并允许按类别筛选
<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>
示例上下文筛选建议查询
http://localhost:8983/solr/techproducts/suggest?suggest=true&suggest.build=true&suggest.dictionary=mySuggester&suggest.q=c&suggest.cfq=memory
建议程序将仅返回标记为“cat=memory”的产品的建议。