8

我正在尝试在 solr 中实现多词同义词,特别是类型

msc divina => divina

因此,如果用户输入“msc divina”,solr 应该只返回“divina”的结果。

schema.xml 中的定义如下所示:

<fieldType name="text_de" class="solr.TextField" positionIncrementGap="100" 
    autoGeneratePhraseQueries="true">
    <analyzer type="index">
        <tokenizer class="solr.WhitespaceTokenizerFactory" />
        <filter class="solr.SynonymFilterFactory"
            synonyms="synonyms_de.txt"
            ignoreCase="true"
            expand="false" />
        <filter class="solr.StopFilterFactory"
            ignoreCase="true"
            words="stopwords_de.txt"
            enablePositionIncrements="true" />
        <filter class="solr.WordDelimiterFilterFactory"
            generateWordParts="1"
            generateNumberParts="1"
            catenateWords="1"
            catenateNumbers="1"
            catenateAll="0"
            splitOnCaseChange="1" />
        <filter class="solr.LowerCaseFilterFactory" />
        <filter class="solr.KeywordMarkerFilterFactory" 
            protected="protwords_de.txt" />
        <filter class="solr.SnowballPorterFilterFactory" language="German2" />
    </analyzer>
    <analyzer type="query">
        <tokenizer class="solr.WhitespaceTokenizerFactory" />
        <filter class="solr.StopFilterFactory"
            ignoreCase="true"
            words="stopwords_de.txt"
            enablePositionIncrements="true" />
        <filter class="solr.WordDelimiterFilterFactory"
            generateWordParts="1"
            generateNumberParts="1"
            catenateWords="0"
            catenateNumbers="0"
            catenateAll="0"
            splitOnCaseChange="1" />
        <filter class="solr.LowerCaseFilterFactory" />
        <filter class="solr.KeywordMarkerFilterFactory" 
            protected="protwords_de.txt" />
        <filter class="solr.SnowballPorterFilterFactory" language="German2" />
    </analyzer>
</fieldType>

它不起作用。如果我向查询分析器添加同义词过滤器,则搜索“msc divina”会返回“msc 和“divina”的每个匹配项。

我该如何解决这个问题?

4

3 回答 3

3

Solr 6.4开始,您需要使用多词同义词solr.SynonymGraphFilterFactory

此过滤器映射单标记或多标记同义词,生成完全正确的图形输出。此过滤器是同义词过滤器的替代品,后者会为多标记同义词生成不正确的图表。

如果在索引期间使用此过滤器,则必须在其后使用 Flatten Graph 过滤器,以像同义词过滤器一样将令牌压在另一个之上,因为索引器不能直接使用图形。当您的同义词替换是多个标记时,要获得完全正确的位置查询,您应该在查询时使用此过滤器应用同义词。

索引时间分析器示例:

<analyzer type="index">
  <tokenizer class="solr.StandardTokenizerFactory"/>
  <filter class="solr.SynonymGraphFilterFactory" synonyms="mysynonyms.txt"/>
  <filter class="solr.FlattenGraphFilterFactory"/> <!-- required on index analyzers after graph filters -->
</analyzer>

由于现在令牌流是图形 - 将为文件的多词同义词提供适当的弧

fast → speedy
wi fi → wifi
wi fi network → hotspot

在此处输入图像描述

在这种情况下 - 多字将正常工作。

参考 McCandless 博客文章 - http://blog.mikemccandless.com/2012/04/lucenes-tokenstreams-are-actually.html

于 2018-05-15T12:56:46.063 回答
1

从 Solr文档

请记住,虽然 SynonymFilter 很乐意处理包含多个单词的同义词(即:“sea biscuit, sea biscit, seabiscuit”),但处理此类同义词的推荐方法是在索引时扩展同义词。这是因为在查询时可能会出现两个潜在问题:

Lucene QueryParser 在将任何文本提供给分析器之前在空白处进行标记,因此如果一个人搜索单词 sea biscit,分析器将分别给出单词“sea”和“biscit”,并且不会知道它们匹配同义词. 短语搜索(即:“sea biscit”)将导致 QueryParser 将整个字符串传递给分析器,但如果 SynonymFilter 配置为扩展同义词,那么当 QueryParser 从分析器获取返回的令牌结果列表时,它将构造一个不会产生预期效果的 MultiPhraseQuery。这是因为分析器可用于指示两个术语占据相同位置的机制有限:无法指示“短语”与术语占据相同位置。

在这里,他们描述了一个问题:除非您使用 ,否则您无法在 indexed 上搜索sea biscit并获得匹配项,但他们还使用多字查询解释了查询时发生的情况,这是您的情况。seabiscuitexpand=true

msc divina -> msc | divina - phrase query

这将匹配 msc 和 divina 文档。如果您可以在查询时指定您的搜索"msc divina"将起作用。

否则,您在查询时需要一个多词识别标记器,或者您可以扩展FieldQParser插件来为您执行此操作。你可以在这里找到更多。

于 2013-11-12T15:01:33.157 回答
1

这是您可以在互联网上找到的解决方案:https ://dzone.com/articles/solution-multi-term-synonyms

除此之外,我对这个问题的解决方案是特定领域的。就我而言,我确定我的查询长度(即少于 200 或只有 5-10 个单词)。

  1. 我在同义词条目中用下划线替换了空格。这是我的同义词之一:

    "like_to":["love_to","loves_to","need_to","needs_to"]
    
  2. 使用 KeywordTokenizerFactory 发送完整查询以进行过滤

    <tokenizer class="solr.KeywordTokenizerFactory"/>
    
  3. minShingleSize使用 ShingleFilterFactory 索引/查询所有可能的大小在和之间的子短语mazShingleSize

    <filter class="solr.ShingleFilterFactory" minShingleSize="2" outputUnigrams="true" maxShingleSize="3"/>
    
  4. 然后使用 PatternReplaceCharFilterFactory 将空格替换为下划线 ( _)

    <charFilter class="solr.PatternReplaceCharFilterFactory" pattern="\\s+" replacement="_"/>
    
  5. 使用您的同义词过滤器工厂。

例子

询问:I love to travel

代币:I love, I love to, love to, love to travel, to travel, tavel

替换为_I_love, I_love_to, love_to, love_to_travel, to_travel, tavel

同义词过滤器将这些变成:I_love, I_love_to, like_to, love_to_travel, to_travel, tavel

因此,它最终会将love to短语更改为like to.

希望这个技巧有所帮助,尽管它涉及昂贵的操作。

于 2018-01-01T08:07:31.247 回答