建议器
Solr 中的 SuggestComponent 为用户提供查询词的自动建议。
您可以使用它在您的搜索应用程序中实现强大的自动建议功能。
虽然可以使用拼写检查功能来支持自动建议行为,但 Solr 有一个专用的 SuggestComponent,专为该功能而设计。
此方法利用 Lucene 的 Suggester 实现,并支持 Lucene 中所有可用的查找实现。
此 Suggester 的主要功能是
-
查找实现的可插拔性
-
术语字典的可插拔性,使您可以灵活地选择字典实现
-
分布式支持
在 Solr 的 “techproducts” 示例中找到的 solrconfig.xml
已经配置了 Suggester 实现。有关搜索组件的更多信息,请参阅请求处理程序和搜索组件部分。
“techproducts” 示例 solrconfig.xml
已经配置了一个 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>
建议器搜索组件参数
建议器搜索组件接受多个配置参数。
查找实现的选择(lookupImpl
,如何在建议字典中找到术语)和字典实现的选择(dictionaryImpl
,如何在建议字典中存储术语)将决定所需的一些参数。
以下是不管使用哪种查找或字典实现都可以使用的主要参数。在以下部分中,为每个实现提供了其他参数。
searchComponent 名称
-
必需
默认:无
整个搜索组件定义的任意名称。
searchComponent 类
-
必需
默认:无
建议器类。应将其定义为
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
,则保留标记之间的分隔符。这意味着建议对标记化敏感(例如,棒球与 base ball 不同)。 preservePositionIncrements
-
可选
默认值:
false
如果为
true
,则建议器将保留位置增量。这意味着,当 Token 过滤器留下空白(例如,当 StopFilter 匹配停用词时)时,在构建建议器时将尊重该位置。
FuzzyLookupFactory
这是一个建议器,它是 AnalyzingSuggester 的扩展,但本质上是模糊的。相似性通过 Levenshtein 算法测量。
此实现使用以下附加属性
exactMatchFirst
-
可选
默认值:
true
如果为
true
,则即使 FST 中的前缀或其他字符串具有更大的权重,也会首先返回精确建议。 preserveSep
-
可选
默认值:
true
如果为
true
,则保留标记之间的分隔符。这意味着建议对标记化敏感(例如,“baseball” 与 “base ball” 不同)。 maxSurfaceFormsPerAnalyzedForm
-
可选
默认值:
256
对于单个分析形式,要保留的最大表面形式数。当有太多表面形式时,我们将丢弃权重最低的那些。
maxGraphExpansions
-
可选
默认值:
-1
构建 FST(“索引时”)时,我们将通过 tokenstream 图的每个路径添加为单独的条目。这会对单个建议添加的扩展数量设置上限。
preservePositionIncrements
-
可选
默认值:
false
如果为
true
,则建议器将保留位置增量。这意味着,当 Token 过滤器留下空白(例如,当 StopFilter 匹配停用词时)时,在构建建议器时将尊重该位置。 maxEdits
-
可选
默认值:
1
允许的最大字符串编辑次数。Solr 的硬限制为
2
。 transpositions
-
可选
默认值:
true
如果为
true
,则应将转置视为原始编辑操作。 nonFuzzyPrefix
-
可选
默认值:
1
必须与建议匹配的公共非模糊前缀匹配的长度。
minFuzzyLength
-
可选
默认值:
3
允许任何字符串编辑之前的查询的最小长度。
unicodeAware
-
可选
默认值:
false
如果为
true
,则maxEdits
、minFuzzyLength
、transpositions
和nonFuzzyPrefix
参数将以 Unicode 代码点(实际字母)而不是字节来衡量。
AnalyzingInfixLookupFactory
分析输入文本,然后基于与索引文本中任何标记的前缀匹配来建议匹配项。这使用 Lucene 索引作为其字典。
此实现使用以下附加属性。
indexPath
-
可选
默认值:请参阅描述
当使用
AnalyzingInfixSuggester
时,您可以提供自己的路径,将在该路径中构建索引。默认值为analyzingInfixSuggesterIndexDir
,它将在您的集合的data/
目录中创建。 minPrefixChars
-
可选
默认值:
4
使用 PrefixQuery 之前的前导字符的最小数量。短于此的前缀将作为字符 n-gram 索引(增加索引大小,但使查找更快)。
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 之前的前导字符的最小数量。短于此的前缀将作为字符 n-gram 索引,这会增加索引大小,但使查找更快。
此实现支持上下文过滤。
FreeTextLookupFactory
它会查看最后一个标记加上用户正在键入的任何最终标记的前缀(如果存在),以预测最可能的下一个标记。还可以指定需要考虑的先前标记的数量。只有当主建议器未能找到任何建议时,才会将此建议器用作后备方案。
此实现使用以下附加属性
suggestFreeTextAnalyzerFieldType
-
必需
默认:无
用于“查询时”和“构建时”分析建议的字段类型。
ngrams
-
可选
默认值:
2
从中创建字典的单个标记的最大数量。增加此值意味着您希望在提出建议时考虑超过前 2 个标记。
FSTLookupFactory
基于自动机的查找。此实现的构建速度较慢,但提供了最低的内存成本。我们建议使用此实现,除非您需要更复杂的匹配结果,在这种情况下,您应该使用 Jaspell 实现。
此实现使用以下附加属性
exactMatchFirst
-
可选
默认值:
true
如果为
true
(默认值),则即使 FST 中的前缀或其他字符串具有更大的权重,也会首先返回精确建议。 weightBuckets
-
可选
默认:无
建议器在构建其字典时将使用的权重单独存储桶的数量。
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
)。示例文件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>
在查询中使用这些 Suggester 时,您需要在请求中定义多个 suggest.dictionary
参数,这些参数引用搜索组件定义中为每个 Suggester 指定的名称。响应将包括每个 Suggester 的部分中的术语。请参阅下面的示例用法部分,了解示例请求和响应。
添加 Suggest 请求处理器
添加搜索组件后,必须将请求处理器添加到 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 请求处理器参数
以下参数允许您为 Suggest 请求处理器设置默认值
suggest
-
可选
默认值:
false
此参数应始终为
true
,因为我们始终希望为此处理器提交的查询运行 Suggester。 suggest.dictionary
-
必需
默认:无
在搜索组件中配置的字典组件的名称。可以在请求处理器中设置,也可以在查询时作为参数发送。
suggest.q
-
可选
默认:无
用于建议查找的查询。如果未提供,则使用
q
参数。 suggest.count
-
可选
默认值:
1
指定 Solr 返回的建议数量。
suggest.cfq
-
可选
默认:无
一个上下文筛选器查询,用于根据上下文字段筛选建议(如果 suggester 支持)。
上下文筛选目前仅受
AnalyzingInfixLookupFactory
和BlendedInfixLookupFactory
支持,并且仅在由Document*Dictionary
支持时才支持。所有其他实现将返回未筛选的匹配项,就好像未请求筛选一样。 suggest.build
-
可选
默认值:
false
如果为
true
,它将构建 suggester 索引。这可能仅对初始请求有用;您可能不希望在每个请求上构建字典,尤其是在生产系统中。如果您想保持字典最新,则应为搜索组件使用buildOnCommit
或buildOnOptimize
参数。 suggest.reload
-
可选
默认值:
false
如果为
true
,它将重新加载 suggester 索引。 suggest.buildAll
-
可选
默认值:
false
如果为
true
,它将构建所有 suggester 索引。 suggest.reloadAll
-
可选
默认值:
false
如果为
true
,它将重新加载所有 suggester 索引。
这些属性也可以在查询时被覆盖,或者根本不在请求处理器中设置,而始终在查询时发送。
示例用法
获取带权重的建议
这是使用单个字典和单个 Solr 核心的基本建议。
示例查询
https://127.0.0.1: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": ""
}
]
}
}
}
}
使用多个字典
如果您定义了多个字典,则可以在查询中使用它们。
示例查询
https://127.0.0.1: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": ""
}
]
}
}
}
}
上下文筛选
上下文筛选允许您通过单独的上下文字段(例如类别、部门或任何其他标记)来筛选建议。AnalyzingInfixLookupFactory
和 BlendedInfixLookupFactory
当前支持此功能,当由 DocumentDictionaryFactory
支持时。
将 contextField
添加到您的 suggester 配置。此示例将建议名称并允许按类别筛选
<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>
示例上下文筛选建议查询
https://127.0.0.1:8983/solr/techproducts/suggest?suggest=true&suggest.build=true&suggest.dictionary=mySuggester&suggest.q=c&suggest.cfq=memory
suggester 将仅返回标记有 'cat=memory' 的产品的建议。