七、Solr 中的拼写检查

拼写检查组件可用于根据索引中的数据建议拼写更正。在本章中,我们将看到如何在索引中启用拼写检查,并使用 PHP 获取和显示拼写更正。我们将在本章中介绍的主题如下:

  • 用于拼写检查的 Solr 配置
  • Solr 中提供的拼写检查器实现
  • 使用 PHP 运行拼写检查查询
  • 显示建议和排序规则
  • 构建自动完成功能

拼写检查对索引词有效。如果我们的索引拼写错误,建议也可能拼写错误。

拼写检查可以通过提供您的意思是功能向用户建议拼写更正。它类似于谷歌提供的显示功能结果的。它可用于提供自动完成用户输入文本的建议列表。PHP 也有一个类似的功能被称为pspell,但这个拼写检查是建立在我们在 Solr 中创建的索引之上的。这意味着它更适合于索引中的文档类型,也可以根据我们更喜欢的结果进行调整。

用于拼写检查的 Solr 配置

Solr 安装附带的演示模式和配置中已经配置了拼写检查。让我们看看它的设置:

  1. <solr_dir>/example/solr/collection1/conf内打开solrconfig.xml
  2. spellcheck名称搜索searchComponent
  3. spellcheck组件内有多个拼写检查器。这是 Solr 附带的default拼写检查工具:

    php <lst name="spellchecker"> <str name="name">default</str> <str name="field">text</str> <str name="classname">solr.DirectSolrSpellChecker</str> <float name="accuracy">0.5</float> <int name="maxEdits">2</int> <int name="minPrefix">1</int> <int name="maxInspections">5</int> <int name="minQueryLength">4</int> <float name="maxQueryFrequency">0.01</float> <float name="thresholdTokenFrequency">.01</float> </lst>

  4. 前面的代码块显示了拼写检查中使用的各种变量。让我们看看拼写检查配置中的重要变量,并检查它们的含义:

    • name:此变量指定 Solr 拼写检查器的拼写检查配置的名称。在我们的配置中,名称为default
    • field:此变量指定将用于拼写检查的字段。我们使用文本字段加载用于拼写检查的标记。
    • classname:此变量指定正在使用的 Solr 拼写检查器的实现。我们正在使用DirectSolrSpellChecker,它直接使用 Solr 索引,不需要我们构建或重建拼写检查索引。我们还将研究其他实现。
    • accuracy:该变量范围为0.01.0,其中1.0最为准确。Solr 拼写检查实现使用此精度值来决定是否可以使用结果。
    • maxQueryFrequency:此变量指定了一个查询词必须出现在其中的文档数的最大阈值,以便将其视为建议。此处设置为0.01。对于较小的索引,阈值越低越好。
    • thresholdTokenFrequency:此变量指定该术语必须出现在%的文档中,以便考虑拼写建议。这就防止了低频术语作为建议提供。但是,如果您的文档库很小,您可能需要进一步减少它以获得拼写建议。

Solr 提供的拼写检查器实现

让我们来看看 Solr 提供的不同拼写检查程序实现:

  • DirectSolrSpellChecker:此实现不需要为拼写检查建立单独的索引。它使用主 Solr 索引提供拼写建议。
  • IndexBasedSpellChecker: This implementation is used to create and maintain a spelling dictionary that is based on the Solr index. Since a separate index is created and maintained, we need to build/rebuild the index whenever the main index changes. This can be done automatically by enabling buildOnCommit or buildOnOptimize in the configuration. Also, we need to specify the location of the index to be created using the spellcheckIndexDir variable in our Solr spellcheck component configuration.

    buildOnCommit组件非常昂贵。建议在 Solr URL 中使用buildOnOptimize或使用spellcheck.build=true显式构建。

  • FileBasedSpellChecker: This implementation uses a flat file to build a spellcheck index in Solr. Since there is no frequency information available, the index created using this component cannot be used to extract frequency based information such as threshold or most popular suggestions. The format of the file is one word per line, for example:

    php Java PHP MySQL Solr

    该索引需要使用 Solr URL 中的spellcheck.build=true参数构建。除了建立和存储索引的spellcheckIndexDir位置外,FileBasedSpellChecker组件还需要sourceLocation变量来指定拼写文件的位置。

  • WordBreakSolrSpellChecker:此拼写检查组件通过组合相邻单词或将单词拆分为多个单词来生成建议。它可以与前面的拼写检查器一起配置。在这种情况下,结果被合并,排序规则可以包含来自两个拼写检查器的结果。

拼写检查器通常给出建议,这些建议按字符串距离计算的分数排序,然后按索引中建议的频率排序。通过使用distanceMeasure变量提供不同的距离计算实现,或通过使用comparatorClass变量提供不同的词频实现,可以在配置文件中调整这些参数。一些可用的comparatorClass实现有score(默认)和freq。类似地,org.apache.lucene.search.spell.JaroWinklerDistance是距离计算的一个实现,可用于 Solr。

使用 PHP 运行拼写检查查询

让我们配置 Solr 以便对两个字段(姓名和作者)进行拼写检查:

  1. 更改schema.xml文件的内容。创建一个将进行拼写检查的新字段,并使用以下代码将nameauthor字段复制到新字段:

    php <field name="spellfld" type="text_general" indexed="true" stored="false" multiValued="true"/> <copyField source="name" dest="spellfld"/> <copyField source="author" dest="spellfld"/>

  2. solrconfig.xml中默认拼写检查器的拼写检查器字段更改为我们刚刚创建的新字段。默认拼写检查器使用 Solr 提供的拼写检查器的DirectSolrSpellChecker实现。

    php <lst name="spellchecker"> <str name="name">default</str> <str name="field">spellfld</str>

  3. 默认情况下,Solr 配置中的/select请求处理程序没有拼写检查设置和结果。因此,让我们将这些变量添加到名为/selectrequestHandler中。在这里,我们指定拼写检查字典作为前面配置的默认,并添加拼写检查组件作为输出的一部分。

    ```php .....
    default on

    spellcheck ```

  4. 现在重新启动 Solr 并重新索引exampledocs文件夹中的books.csv文件以及第 5 章中提供的books.csv文件,使用 PHP 和 Solr突出显示结果。我们之所以需要再次为书籍编制索引,是因为我们改变了模式。无论何时更改架构并添加新字段,都需要再次索引文档以填充新字段中的数据。请参阅第 2 章中的向 Solr 索引添加示例文档章节从 Solr插入、更新和删除文档,为 Solr 中的这些 CSV 文件编制索引。

让我们使用 PHP 对作者斯蒂芬·金进行拼写检查,并查看索尔建议的更正:

  1. 首先使用以下代码从 select 查询中获取拼写检查组件:

    php $spellChk = $query->getSpellcheck(); $spellChk->setCount(10); $spellChk->setCollate(true); $spellChk->setExtendedResults(true); $spellChk->setCollateExtendedResults(true);

  2. 我们已经设置了通过setCount()功能返回的建议数量。通过将setCollate()设置为true,我们告诉 Solr 建议原始查询字符串,并用最佳建议替换原始拼写错误的单词。setExtendedResults()setCollateExtendedResults()函数告诉 Solr 提供有关建议和返回的排序规则的附加信息。如果需要,可将其用于分析。

  3. 执行查询后,我们需要从查询结果集中获取拼写检查组件,并使用它获取建议和排序规则。我们使用getCorrectlySpelled()函数检查查询的拼写是否正确。

    php $resultset = $client->select($query); $spellChkResult = $resultset->getSpellcheck(); if ($spellChkResult->getCorrectlySpelled()) { echo 'yes'; }else{ echo 'no'; }

  4. 接下来,我们循环检查拼写检查结果,对于查询中的每个术语,我们得到建议和相关细节,例如建议的数量、原始术语的频率以及建议的单词及其出现频率。

    php foreach($spellChkResult as $suggestion) { echo 'NumFound: '.$suggestion->getNumFound().'<br/>'; echo 'OriginalFrequency: '.$suggestion->getOriginalFrequency().'<br/>'; foreach ($suggestion->getWords() as $word) { echo 'Frequency: '.$word['freq'].'<br/>'; echo 'Word: '.$word['word'].'<br/>'; } }

  5. 类似地,我们获得排序规则并循环通过它来获得正确的查询和命中。我们还可以在查询中得到每个术语的更正细节。

    php $collations = $spellChkResult->getCollations(); echo '<h1>Collations</h1>'; foreach($collations as $collation) { echo 'Query: '.$collation->getQuery().'<br/>'; echo 'Hits: '.$collation->getHits().'<br/>'; foreach($collation->getCorrections() as $input => $correction) { echo $input . ' => ' . $correction .'<br/>'; } }

使用 PHP 和 Solr 实现自动完成功能

自动完成功能可以通过在 Solr 中创建一个 Suggester 并使用 Solarium 中提供的 Suggester 来构建。自动完成的目的是根据不完整的用户输入建议查询条件。Suggester 的工作原理与拼写检查功能非常相似。它可以用于主索引或任何其他字典。

首先让我们更改schema.xml文件,添加名为suggest的拼写检查组件:

<searchComponent name="suggest" class="solr.SpellCheckComponent">
<lst name="spellchecker">
<str name="name">suggest</str>
<str name="field">suggestfld</str>
<str name="classname">org.apache.solr.spelling.suggest.Suggester</str>
<str name="lookupImpl">org.apache.solr.spelling.suggest.tst.TSTLookup</str>
<str name="storeDir">suggest_idx</str>
<float name="threshold">0.005</float>
<str name="buildOnCommit">true</str>
</lst>
</searchComponent>

我们已将用于建议的字段指定为suggestfld。用于构建 Suggester 的 Solr 组件在类名中称为org.apache.solr.spelling.suggest.Suggester。阈值是一个介于 0 和 1 之间的值,用于指定应将术语添加到查找词典中的文档的最小部分。我们正在suggest_idx文件夹中存储索引。lookupImpl组件提供用于创建建议的inmemory查找实现。Solr 中可用的查找实现有:

  • JaspellLookup:基于 Jaspell 的树表示。Jaspell 是一个 Java 拼写检查包,它为拼写更正创建了一个复杂的基于树的结构。它使用一个名为trie的数据结构。
  • TSTLookup:它是一种基于的简单紧凑的三元树表示法,能够立即更新数据结构。它还使用了trie数据结构。
  • FSTLookup:基于自动机的表示。它的构建速度较慢,但在运行时消耗的内存要少得多。
  • WFSTLookup:它是加权自动机表示,是FSTLookup的一种替代方案,用于更细粒度的排名。

您可以更改查找实现,并查看建议是如何更改的。由于建议基于索引外,因此索引越大,建议越好。

让我们在 Solr 中为建议创建一个单独的请求处理程序,并在其中添加建议拼写检查作为一个组件。用于提供建议的默认配置选项包含在请求处理程序本身中。

<requestHandler class="org.apache.solr.handler.component.SearchHandler" name="/suggest">
<lst name="defaults">
<str name="spellcheck">true</str>
<str name="spellcheck.dictionary">suggest</str>
<str name="spellcheck.onlyMorePopular">true</str>
<str name="spellcheck.count">5</str>
<str name="spellcheck.collate">true</str>
</lst>
<arr name="components">
<str>suggest</str>
</arr>
</requestHandler>

接下来,我们需要在schema.xml中创建一个单独的字段,该字段被索引。我们正在将书名、作者和标题复制到字段中提供建议。

<field name="suggestfld" type="text_general" indexed="true" stored="false" multiValued="false"/>

<copyField source="name" dest="suggestfld"/>
<copyField source="author" dest="suggestfld"/>
<copyField source="title" dest="suggestfld"/>

完成后,重新启动 Apache Tomcat web 服务器,并使用以下 URL 构建拼写检查索引:

http://localhost:8080/solr/collection1/suggest/?spellcheck.build=true

我们创建了一个名为 suggest 的单独请求处理程序,因此我们的 URL 是/suggest/,而不是/select

现在让我们来看 Solarium 库提供的与 PHP 集成的建议。首先,我们需要从 Solarium 客户端创建 Suggester 查询,而不是普通查询。

$client = new Solarium\Client($config);
$suggestqry = $client->createSuggester();

接下来我们必须设置要使用的请求处理程序。记住,我们创建了一个名为建议的单独请求处理程序来提供建议。还要设置我们要使用的词典。我们可以创建多个字典,并在运行时使用以下函数进行更改:

$suggestqry->setHandler('suggest');
$suggestqry->setDictionary('suggest');

现在为建议者提供查询。设置要返回的建议数。打开collation标志和onlyMorePopular标志。

$suggestqry->setQuery('ste');
$suggestqry->setCount(5);
$suggestqry->setCollate(true);
$suggestqry->setOnlyMorePopular(true);

使用suggester()函数执行查询,然后循环搜索结果集以获取所有术语及其建议。原始查询可以通过getQuery()功能显示。

$resultset = $client->suggester($suggestqry);
echo "Query : ".$suggestqry->getQuery();
foreach ($resultset as $term => $termResult) {
    echo '<strong>' . $term . '</strong><br/>';
    echo 'Suggestions:<br/>';
    foreach($termResult as $result){
        echo '-> '.$result.'<br/>';
    }
}

最后,使用以下代码获取并显示排序规则:

echo 'Collation: '.$resultset->getCollation();

这段代码可用于创建 AJAX 调用,并以 JSON 或 XML 字符串的形式提供自动完成建议。

总结

我们从了解拼写检查如何在 Solr 上工作开始。我们讨论了 Solr 用于创建拼写检查索引的配置,并看到了 Solr 提供的拼写检查程序的不同实现。我们了解了 Solr 中拼写检查中可用的一些微调选项。接下来,我们在 Solr 中创建了一个字段,用于对书名和作者进行拼写检查,并配置 Solr 以使用该字段提供拼写建议。我们看到了拼写检查的一种变体,可以用来为自动补全提供拼写建议。我们为自动完成建议创建了一个单独的 Solr 索引,并查看了 PHP 代码,该代码使用三个字符的单词并从索引中提供建议。