拼写检查

拼写检查组件旨在根据其他相似的词语提供内联查询建议。

这些建议的基础可以是 Solr 中字段中的词语、外部创建的文本文件或其他 Lucene 索引中的字段。

配置 SpellCheckComponent

在 solrconfig.xml 中定义拼写检查

第一步是在 solrconfig.xml 中指定词语的来源。Solr 中有多种拼写检查方法,如下所述。

IndexBasedSpellChecker

IndexBasedSpellChecker 使用 Solr 索引作为用于拼写检查的并行索引的基础。它需要将一个字段定义为索引词语的基础;一种常见的做法是将一些字段(如 titlebody 等)的词语复制到另一个为拼写检查创建的字段。以下是在 solrconfig.xml 中配置 IndexBasedSpellChecker 的示例

<searchComponent name="spellcheck" class="solr.SpellCheckComponent">
  <lst name="spellchecker">
    <str name="classname">solr.IndexBasedSpellChecker</str>
    <!-- required parameters -->
    <str name="field">content</str>
    <!-- optional parameters for IndexBasedSpellChecker -->
    <str name="sourceLocation">./folder/with/index/files</str>
    <!-- optional parameters for all spellcheckers -->
    <str name="spellcheckIndexDir">./spellcheckerDir</str>
    <str name="name">default</str>
    <str name="fieldType">content_ft</str>
    <str name="queryAnalyzerFieldType">text_general</str>
    <str name="distanceMeasure">org.apache.lucene.search.spell.LevenshteinDistance</str>
    <str name="comparatorClass">score</str>
    <float name="accuracy">0.5</float>
    <float name="thresholdTokenFrequency">0.0</float>
    <str name="buildOnCommit">true</str>
    <str name="buildOnOptimize">false</str>
 </lst>
</searchComponent>

第一个元素定义使用 solr.SpellCheckComponentsearchComponentclassname 是 SpellCheckComponent 的特定实现,在本例中为 solr.IndexBasedSpellChecker。定义 classname 是可选的;如果未定义,则默认设置为 IndexBasedSpellChecker

spellcheckIndexDir 定义保存拼写检查索引的目录的位置,而 field 定义拼写检查词语的源字段(在模式中定义)。在为拼写检查索引选择字段时,最好避免使用经过大量处理的字段,以获得更准确的结果。如果该字段通过处理同义词和/或词干提取有许多单词变体,则将使用这些变体以及更有效的拼写数据来创建字典。

默认情况下,此拼写检查器从 Solr 索引构建其字典。可以通过指定 sourceLocation 来更改此设置,sourceLocation 是一个包含静态 Lucene 索引文件的文件夹,用于代替 Solr 索引。

拼写检查器可以分配一个描述性标签 name,如果搜索组件定义了多个拼写检查器,这会很有帮助。这样,拼写检查查询就可以识别应咨询的拼写检查器的子集(有关更多详细信息,请参阅拼写检查参数)。

field 的查询分析器用于标记拼写检查查询。如果需要覆盖该行为,请配置一个 fieldType,拼写检查器将改为使用该字段类型的查询分析器。

queryAnalyzerFieldType 是 Solr 模式中的字段类型,其工作方式与 fieldType 参数类似。主要区别在于,Solr 在对通过 spellcheck.q 提供的拼写检查查询进行标记时使用 fieldfieldType,而当通过 q 参数提供查询时使用 queryAnalyzerFieldType

此参数指定的字段类型应执行最少的转换。通常,最好避免使用积极词干提取或 NGram 的类型,因为这些类型的分析会扰乱拼写检查。

常见的配置参数,如 distanceMeasurecomparatorClassaccuracythresholdTokenFrequency,可控制返回的拼写检查建议。

如果未指定 distanceMeasure,Solr 将使用 Levenshtein 度量,这也是其他拼写检查器实现(DirectSolrSpellChecker 除外)的默认度量。

comparatorClass 配置为 "score" 时,距离较小(即相似度较高)的建议被认为更相关。另一个值是 "freq" - 这会优先考虑文档频率较高的建议。

accuracy 设置定义了有效建议的阈值,而 thresholdTokenFrequency 设置允许跳过在索引中文档频率较低的建议。

最后,buildOnCommitbuildOnOptimize 定义是否在每次提交(即每次向索引添加新文档时)或每次优化请求时构建拼写检查索引。两者都是可选的,如果您希望将其值设置为 false,则可以省略。

DirectSolrSpellChecker

DirectSolrSpellChecker 使用 Solr 索引中的术语,而无需像 IndexBasedSpellChecker 那样构建并行索引。此拼写检查器的好处是不需要定期构建,这意味着术语始终与索引中的术语保持同步。以下是如何在 solrconfig.xml 中配置此拼写检查器的示例:

<searchComponent name="spellcheck" class="solr.SpellCheckComponent">
  <lst name="spellchecker">
    <str name="classname">solr.DirectSolrSpellChecker</str>
    <!-- required parameters -->
    <str name="field">name</str>
    <!-- optional parameters for DirectSolrSpellChecker -->
    <int name="maxEdits">2</int>
    <int name="minPrefix">1</int>
    <int name="maxInspections">5</int>
    <int name="minQueryLength">4</int>
    <int name="maxQueryLength">40</int>
    <float name="maxQueryFrequency">0.01</float>
    <!-- optional parameters for all spellcheckers -->
    <str name="name">default</str>
    <str name="fieldType">name</str>
    <str name="queryAnalyzerFieldType">text_general</str>
    <str name="distanceMeasure">internal</str>
    <str name="comparatorClass">score</str>
    <float name="accuracy">0.5</float>
    <float name="thresholdTokenFrequency">0.0</float>
  </lst>
</searchComponent>

为该拼写检查器选择要查询的 field 时,您需要选择一个执行的分析相对较少的字段(特别是诸如词干提取之类的分析)。请注意,您需要指定一个字段用于建议,因此与 IndexBasedSpellChecker 一样,您可能需要将诸如 titlebody 等字段的数据复制到一个专门用于提供拼写建议的字段。

许多参数都与此拼写检查器应如何查询索引以获取术语建议有关。distanceMeasure 定义了在拼写检查查询期间使用的度量 - 此拼写检查器的默认值为 "internal",它对应于 Damerau-Levenshtein 度量。

由于此拼写检查器正在查询主索引,您可能需要限制其查询索引的频率,以确保避免与用户查询发生任何性能冲突。accuracy 设置定义了有效建议的阈值,而 maxEdits 定义了允许对术语进行的更改次数。由于大多数拼写错误只差一个字母,因此将其设置为 1 将减少可能的建议数量(但是,默认值为 2);该值只能为 1 或 2。minPrefix 定义了术语应共享的最小字符数。例如,将其设置为 1 意味着拼写建议都将以相同的字母开头。

maxInspections 参数定义了在返回结果之前要检查的最大可能匹配项数;默认值为 5。minQueryLength 定义了在提供建议之前查询中必须包含的最小字符数;默认值为 4。maxQueryLength 使拼写检查器能够跳过非常长的查询术语,这可以避免昂贵的操作或异常。默认情况下,术语长度没有限制。

首先,拼写检查器通过在索引中查找来分析传入的查询词。只有索引中不存在或过于罕见(等于或低于 maxQueryFrequency)的查询词才会被视为拼写错误,并用于查找建议。频率高于 maxQueryFrequency 的词将绕过拼写检查器,保持不变。在找到每个拼写错误的单词的建议后,将使用 thresholdTokenFrequency 作为边界值来筛选其频率是否足够。这些参数(maxQueryFrequencythresholdTokenFrequency)可以是表示为小于 1 的十进制值的百分比(例如 0.011%),也可以是绝对值(例如 4)。

maxQueryFrequency 指定为百分比时,它将在每个分片上独立评估(相对于该分片的 maxDoc),以确定是否应将其视为拼写错误。如果术语分布在分片之间不均匀,则一些不常见的术语可能会被认为是拼写正确的,并且不会生成预期的建议。

FileBasedSpellChecker

FileBasedSpellChecker 使用外部文件作为拼写词典。如果您将 Solr 用作拼写服务器,或者拼写建议不需要基于索引中的实际术语,这将非常有用。在 solrconfig.xml 中,您将按如下方式定义 searchComponent:

<searchComponent name="spellcheck" class="solr.SpellCheckComponent">
  <lst name="spellchecker">
    <str name="classname">solr.FileBasedSpellChecker</str>
    <!-- required parameters -->
    <str name="sourceLocation">spellings.txt</str>
    <!-- optional parameters for FileBasedSpellChecker -->
    <str name="fieldType">text_general</str>
    <str name="characterEncoding">UTF-8</str>
    <!-- optional parameters for all spellcheckers -->
    <str name="spellcheckIndexDir">./spellcheckerDir</str>
    <str name="name">file</str>
    <str name="queryAnalyzerFieldType">text_general</str>
    <str name="distanceMeasure">org.apache.lucene.search.spell.LevenshteinDistance</str>
    <str name="comparatorClass">score</str>
    <float name="accuracy">0.5</float>
    <float name="thresholdTokenFrequency">0.0</float>
    <bool name="buildOnCommit">false</bool>
    <bool name="buildOnOptimize">false</bool>
 </lst>
</searchComponent>

配置与 IndexBasedSpellChecker 非常相似,此处的差异在于使用 sourceLocation 来定义术语文件的位置,以及使用 characterEncoding 来定义术语文件的编码。

如果指定了 fieldType 参数并且与 Solr 架构中的类型匹配,则 Solr 将通过首先使用 fieldType 索引分析器标记化外部文件中的每一行,然后将每个标记添加到索引来构建拼写检查索引。

否则,Solr 会将外部文件中的每一行都视为一个单独的标记,并将其原样添加到拼写检查索引。

在前面的示例中,name 用于命名此拼写检查器的特定定义。多个定义可以共存于一个 solrconfig.xml 中,而 name 有助于区分它们。如果仅定义一个拼写检查器,则不需要名称。

WordBreakSolrSpellChecker

WordBreakSolrSpellChecker 通过组合相邻的查询词和/或将术语分解为多个单词来提供建议。它是 SpellCheckComponent 的增强功能,利用了 Lucene 的 WordBreakSpellChecker。它可以检测由错位的空格导致的拼写错误,而无需使用基于 shingle 的字典,并为断词错误提供校对支持,包括用户在同一查询中混合使用单字拼写错误和断词错误的情况。它还提供分片支持。

以下是如何在 solrconfig.xml 中配置它的示例:

<searchComponent name="spellcheck" class="solr.SpellCheckComponent">
  <lst name="spellchecker">
    <str name="classname">solr.WordBreakSolrSpellChecker</str>
    <!-- required parameters -->
    <str name="field">lowerfilt</str>
    <!-- optional parameters for WordBreakSpellChecker -->
    <str name="combineWords">true</str>
    <str name="breakWords">true</str>
    <str name="breakSuggestionTieBreaker">max_freq</str>
    <int name="maxChanges">1</int>
    <int name="maxCombinedLength">20</int>
    <int name="minBreakLength">1</int>
    <int name="maxEvaluations">1000</int>
    <int name="minSuggestionFreq">1</int>
    <!-- optional parameters for all spellcheckers -->
    <str name="name">wordbreak</str>
    <str name="fieldType">lowerfilt_ft</str>
    <str name="queryAnalyzerFieldType">text_general</str>
  </lst>
</searchComponent>

某些参数应该在其他拼写检查器的讨论中很熟悉,例如 nameclassnamefield。此拼写检查器的新参数是 combineWords,它定义是否应在字典搜索中组合单词(默认为 true);以及 breakWords,它定义是否应在字典搜索期间分解单词(默认为 true)。

maxChanges 是一个整数,它定义了拼写检查器应检查校对可能性与索引的次数。

maxCombinedLength 允许跳过过长的建议。同样,minBreakLength 指示拼写检查器不要将单词分解成太短的部分。

maxEvaluations 定义要评估的最大单词组合数 - 较高的值可能会提高结果质量,而较低的值可能会提高性能。

minSuggestionFreq 设置一个术语要包含为建议的一部分必须具有的最小频率。

最后,breakSuggestionTieBreaker 设置("max_freq" 或 "sum_freq")指示 Solr 按断词的数量对建议进行排序,然后分别按所有组件术语的最大频率或总和进行排序。

拼写检查器可以与传统的检查器(即 DirectSolrSpellChecker)一起配置。结果被组合在一起,并且校对可以包含来自两个拼写检查器的更正的组合。

将其添加到请求处理程序

查询将被发送到请求处理程序。如果每个请求都应生成建议,则应将以下内容添加到您正在使用的 requestHandler 中:

<str name="spellcheck">true</str>

可能的参数之一是要使用的 spellcheck.dictionary,并且可以定义多个。使用多个字典时,将查询所有指定的字典并交错显示结果。校对是使用不同拼写检查器的组合创建的,并注意在同一校对中不会发生多个重叠的更正。

以下是一个包含多个字典的示例:

<requestHandler name="spellCheckWithWordbreak" class="org.apache.solr.handler.component.SearchHandler">
  <lst name="defaults">
    <str name="spellcheck.dictionary">default</str>
    <str name="spellcheck.dictionary">wordbreak</str>
    <str name="spellcheck.count">20</str>
  </lst>
  <arr name="last-components">
    <str>spellcheck</str>
  </arr>
</requestHandler>

拼写检查参数

SpellCheck 组件接受以下描述的参数。

spellcheck

可选

默认值:false

此参数为请求启用 SpellCheck 建议。如果为 true,则将生成拼写建议。如果需要拼写检查,则这是必需的。

spellcheck.qq

可选

默认值:无

此参数指定要进行拼写检查的查询。

如果定义了 spellcheck.q,则使用它;否则,使用原始输入查询。spellcheck.q 参数旨在成为原始查询,减去任何额外的标记,如字段名称、提升等。如果指定了 q 参数,则使用 SpellingQueryConverter 类将其解析为标记;否则使用WhitespaceTokenizer

选择使用哪个取决于应用程序。本质上,如果您的应用程序中有一个“准备就绪”的拼写版本,那么最好使用 spellcheck.q。否则,如果您只想让 Solr 完成工作,请使用 q 参数。

SpellingQueryConverter 类不能正确处理非 ASCII 字符。在这种情况下,您必须使用 spellcheck.q 或实现您自己的 QueryConverter。
spellcheck.build

可选

默认值:false

如果设置为 true,则此参数会创建用于拼写检查的字典。在典型的搜索应用程序中,您需要在使用拼写检查之前构建字典。但是,并非总是需要先构建字典。例如,您可以配置拼写检查器以使用已存在的字典。

构建字典需要一些时间,因此不应随每个请求发送此参数。

spellcheck.reload

可选

默认值:false

如果设置为 true,则此参数会重新加载拼写检查器。结果取决于 SolrSpellChecker.reload() 的实现。在典型的实现中,重新加载拼写检查器意味着重新加载字典。

spellcheck.count

可选

默认值:请参阅描述

此参数指定拼写检查器应为术语返回的最大建议数。如果未设置此参数,则该值默认为 1。如果设置了该参数但未分配数字,则该值默认为 5。如果将该参数设置为正整数,则该数字将成为拼写检查器返回的最大建议数。

spellcheck.onlyMorePopular

可选

默认值:false

如果为 true,则 Solr 将返回比现有查询命中更多的查询的建议。请注意,即使给定的查询词在索引中存在并被认为是“正确的”,这也会返回更受欢迎的建议。

spellcheck.maxResultsForSuggest

可选

默认值:无

例如,如果将其设置为 5 并且用户的查询返回 5 个或更少的结果,则拼写检查器将报告 "correctlySpelled=false" 并提供建议(如果请求,则提供校对)。将此值设置为大于零对于为返回少量命中的查询创建“您是不是要找?”建议非常有用。

spellcheck.alternativeTermCount

可选

默认值:无

定义为索引和/或字典中存在的每个查询词返回的建议数。据推测,对于 docFrequency>0 的单词,用户将需要更少的建议。此外,设置此值会启用上下文相关的拼写建议。

spellcheck.extendedResults

可选

默认值:false

如果为 true,则此参数会导致 Solr 返回有关拼写检查结果的其他信息,例如索引中每个原始术语的频率 (origFreq) 以及索引中每个建议的频率 (frequency)。请注意,此结果格式与非扩展格式不同,因为返回的单词建议实际上是列表的数组,其中每个列表都包含建议的术语及其频率。

spellcheck.collate

可选

默认值:false

如果为 true,则此参数指示 Solr 为每个标记(如果存在)采用最佳建议,并从建议中构建新查询。

例如,如果输入查询是 "jawa class lording",而 "jawa" 的最佳建议是 "java","lording" 的最佳建议是 "loading",那么最终的校对结果将是 "java class loading"。

spellcheck.collate 参数只返回保证在重新查询时能够产生匹配结果的校对结果,即使应用了原始的 fq 参数也是如此。当每个查询有多个更正时,这尤其有用。

此参数仅返回要使用的查询,并不会实际运行建议的查询。
spellcheck.maxCollations

可选

默认值:1

返回的最大校对数量。如果 spellcheck.collate 为 false,则忽略此参数。

spellcheck.maxCollationTries

可选

默认值:0

此参数指定 Solr 在放弃之前尝试的校对可能性数量。较低的值可确保更好的性能。可能需要更高的值才能找到可以返回结果的校对。默认值 0 等同于不检查校对。如果 spellcheck.collate 为 false,则忽略此参数。

spellcheck.maxCollationEvaluations

可选

默认值:10000

此参数指定在决定要针对索引测试哪些校对候选之前,要排名和评估的最大单词更正组合数量。这是为了在用户输入包含许多拼写错误的单词的查询时,作为一种性能安全网。

spellcheck.collateExtendedResults

可选

默认值:false

如果为 true,此参数将返回详细说明 Solr 找到的校对的扩展响应格式。如果 spellcheck.collate 为 false,则忽略此参数。

spellcheck.collateMaxCollectDocs

可选

默认值:0

此参数指定在针对索引测试潜在的校对时应收集的最大文档数量。值为 0 表示应收集所有文档,从而产生精确的命中计数。否则,将提供估计值,作为在不需要精确命中计数的情况下进行性能优化的方法——指定的值越高,估计值越精确。

spellcheck.collateExtendedResultsfalse 时,始终使用优化,就好像指定了 1 一样。

spellcheck.collateParam.* 前缀

可选

默认值:无

此参数前缀可用于指定您希望 Spellchecker 在内部验证校对查询时使用的任何其他参数。例如,即使您的常规搜索结果允许通过诸如 q.op=ORmm=20% 之类的参数对一个或多个查询词进行宽松匹配,您也可以指定覆盖参数,例如 spellcheck.collateParam.q.op=AND&spellcheck.collateParam.mm=100%,以要求只返回由至少在一个文档中找到的所有单词组成的校对。

spellcheck.dictionary

可选

默认值:default

此参数使 Solr 使用参数的参数中命名的字典。此参数可用于在每个请求的基础上调用特定的拼写检查器。

spellcheck.accuracy

可选

默认值:请参阅描述

指定拼写检查实现用于决定结果是否值得的准确度值。该值是介于 0 和 1 之间的浮点数。默认为 Float.MIN_VALUE

spellcheck.<DICT_NAME>.key

可选

默认值:无

指定处理给定字典的实现的键/值对。传递的值仅为 key=valuespellcheck.<DICT_NAME>. 被剥离)。

例如,给定一个名为 foo 的字典,spellcheck.foo.myKey=myValue 将导致 myKey=myValue 被传递给处理字典 foo 的实现。

拼写检查示例

使用 Solr 的 bin/solr start -e techproducts 示例,此查询显示了一个简单请求的结果,该请求使用 spellcheck.q 参数定义查询,并强制校对要求所有输入术语都必须匹配

https://127.0.0.1:8983/solr/techproducts/spell?df=text&spellcheck.q=delll+ultra+sharp&spellcheck=true&spellcheck.collateParam.q.op=AND&wt=xml

结果

<lst name="spellcheck">
  <lst name="suggestions">
    <lst name="delll">
      <int name="numFound">1</int>
      <int name="startOffset">0</int>
      <int name="endOffset">5</int>
      <int name="origFreq">0</int>
      <arr name="suggestion">
        <lst>
          <str name="word">dell</str>
          <int name="freq">1</int>
        </lst>
      </arr>
    </lst>
    <lst name="ultra sharp">
      <int name="numFound">1</int>
      <int name="startOffset">6</int>
      <int name="endOffset">17</int>
      <int name="origFreq">0</int>
      <arr name="suggestion">
        <lst>
          <str name="word">ultrasharp</str>
          <int name="freq">1</int>
        </lst>
      </arr>
    </lst>
  </lst>
  <bool name="correctlySpelled">false</bool>
  <lst name="collations">
    <lst name="collation">
      <str name="collationQuery">dell ultrasharp</str>
      <int name="hits">1</int>
      <lst name="misspellingsAndCorrections">
        <str name="delll">dell</str>
        <str name="ultra sharp">ultrasharp</str>
      </lst>
    </lst>
  </lst>
</lst>

分布式拼写检查

SpellCheckComponent 也支持在分布式索引上进行拼写检查。如果您在 "/select" 之外的请求处理程序上使用 SpellCheckComponent,则必须提供以下两个参数

shards

必需

默认值:无

指定分布式索引配置中的分片。有关分布式索引的更多信息,请参阅 Solr 集群类型

shards.qt

必需

默认值:无

指定 Solr 用于向分片发出请求的请求处理程序。对于 /select 请求处理程序,此参数不是必需的。

例如

https://127.0.0.1:8983/solr/techproducts/spell?spellcheck=true&spellcheck.build=true&spellcheck.q=toyata&shards.qt=/spell&shards=solr-shard1:8983/solr/techproducts,solr-shard2:8983/solr/techproducts

在对 SpellCheckComponent 进行分布式请求的情况下,即使 spellcheck.count 参数值小于 5,也会请求分片至少提供 5 个建议。收集建议后,它们会根据配置的距离度量(默认为 Levenshtein 距离)进行排名,然后再根据聚合频率进行排名。