建议器

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

可选

默认值:无

存储词典文件的位置。

buildOnCommitbuildOnOptimize

可选

默认值: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

转置

可选

默认值:true

如果为 true,则应将转置视为原始编辑操作。

nonFuzzyPrefix

可选

默认值:1

必须与建议匹配的公共非模糊前缀匹配的长度。

minFuzzyLength

可选

默认值:3

允许任何字符串编辑操作之前的查询的最小长度。

unicodeAware

可选

默认值:false

如果为 true,则 maxEditsminFuzzyLengthtranspositionsnonFuzzyPrefix 参数将以 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

可选

默认值:无

建议者在构建其词典时将使用的权重的单独存储桶的数量。

TSTLookupFactory

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

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

介于 01 之间的值,表示术语应出现在总文档中的最小分数,才能添加到查找词典中。

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

可选

默认值:无

如果建议器支持,则用于根据上下文字段过滤建议的 上下文筛选器 查询。

目前,只有 AnalyzingInfixLookupFactoryBlendedInfixLookupFactory 支持上下文筛选,并且仅当由 Document*Dictionary 支持时才支持。所有其他实现都将返回未筛选的匹配项,就像未请求筛选一样。

suggest.build

可选

默认值:false

如果为 true,它将构建建议器索引。这可能仅对初始请求有用;您可能不想在每个请求上构建词典,尤其是在生产系统中。如果您希望保持词典是最新的,则应为搜索组件使用 buildOnCommitbuildOnOptimize 参数。

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 构建建议词典(但请注意,您可能不想在每次查询时都构建索引 - 如果您的文档经常更改,则应该使用 buildOnCommitbuildOnOptimize)。

示例响应

{
  "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 支持时,AnalyzingInfixLookupFactoryBlendedInfixLookupFactory 目前支持此功能。

contextField 添加到您的建议程序配置中。此示例将建议名称,并允许按类别筛选

solrconfig.xml
<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”的产品的建议。