2

我们有一个基于 Solr 的搜索系统,它使用 C# 中的 Solrnet 库,它支持一些高级搜索功能,如模糊、同义词和词干。虽然所有这些都有效,但对词干搜索的期望似乎是通过缩减词干提取和通过扩展词干提取以涵盖单词的语法变化。一个用例会更清楚:

  • 寻找鱼也会找到钓鱼
  • 搜索已应用也会找到应用、应用和应用

我们使用带有 SnowballPorterFilterFactory 的 CopyField 实现了词干提取。结果,当搜索燃烧时,结果返回燃烧燃烧,但是当搜索燃烧时,结果没有返回燃烧燃烧燃烧

由于所有支持 Lucene/Solr 的词干分析器都使用归约词干提取,我们不确定如何处理。根据 Solr 维基:

词干提取的相关技术是词形还原,它允许通过扩展“词干”,获取词根并将其“扩展”为所有各种形式。词形还原可以在插入时或查询时使用。Lucene/Solr 没有对词形还原的内置支持,但可以使用您自己的字典和 SynonymFilterFactory 来模拟它

我们不确定如何在 Solr 中解决这个问题。有任何想法吗。

我们还考虑使用一些基于 C# 的词干分析器/词元分析器库来获取单词的根,并使用一些公共数据库(如 WordNet)来提取词干的不同语法变体,然后将所有这些术语发送到 Solr 中进行查询。我们还没有做很多研究来找出一个稳定的 C# 词干分析器/词形提取器和一个 WordNet C# API,但看起来这太复杂了,它应该有一种从 Solr 中执行的方法。

Solr Schema 的相关部分:

<field name="Content" type="text_general" indexed="false" stored="true" required="true"/>
<field name="ContentSearch" type="text_general" indexed="true" stored="false" multiValued="true"/>
<field name="ContentSearchStemming" type="text_stem" indexed="true" stored="false" multiValued="true"/>

<copyField source="Content" dest="ContentSearch"/>
<copyField source="Content" dest="ContentSearchStemming"/>

<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
  <analyzer type="index">
    <tokenizer class="solr.StandardTokenizerFactory"/>
    <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
    <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>
  <analyzer type="query">
    <tokenizer class="solr.StandardTokenizerFactory"/>
    <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
    <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>
</fieldType>

<fieldType name="text_stem" class="solr.TextField" >
    <analyzer>
       <tokenizer class="solr.WhitespaceTokenizerFactory"/>
       <filter class="solr.SnowballPorterFilterFactory"/>
    </analyzer>          
 </fieldType>

当我为文档编制索引时,内容将按原样存储在 Content 字段中,并分别复制到 ContentSearch 和 ContentSearchStemming 以进行基于文本的搜索和词干搜索。因此,ContentSearchStemming 字段确实存储了词干/简化形式。我已经使用 Luke 以及 Admin Schema Browser --> Term Info 进行了检查。在 Admin Analysis 屏幕中,我测试并发现如果我索引文本“burning”,它会被缩减为并存储为“burn”。到目前为止,一切都很好。

现在在 UI 中,

  • 假设用户输入术语“burn”并检查词干选项。期望是,由于用户已指定词干,因此应返回术语“burn”以及所有词干为的词的结果“烧”即烧、烧、烧等。
  • 假设用户输入术语“刻录”并检查词干选项。期望是,由于用户已指定词干,因此应返回术语“burning”以及所有词干为“burn”的词(即burn、burn、burns等)的结果。

提交给 Solr 的查询:

q=ContentSearchStemming:burning

从调试信息:

<str name="rawquerystring">ContentSearchStemming:burning</str>
<str name="querystring">ContentSearchStemming:burning</str>
<str name="parsedquery">ContentSearchStemming:burn</str>
<str name="parsedquery_toString">ContentSearchStemming:burn</str>

因此,当返回结果时,我只会使用“burn”一词突出显示命中,尽管同一个文档包含诸如burning 和burns 之类的术语。

我认为词干应该像这样工作:

  1. 查询分析器链中的词干过滤器会将输入词缩减为其词干。燃烧 --> 燃烧
  2. 查询组件应该扫描这些术语并匹配那些在术语的词干与输入词的词干之间找到匹配的词。烧伤-->烧伤(匹配)烧伤-->烧伤

第一点正在发生。但看起来它正在执行与词干“burn”匹配的基于精确文本的搜索。因此,烧伤或烧伤不会得到回报。

希望我能够说清楚。

4

0 回答 0