SOLR SynonymFilter和WordDelimiter问题

时间:2013-03-07 14:51:34

标签: solr lucene

1。我在做什么:

我目前正在尝试实施一些流行的同义词,以增加展示广告的数量。


2。限制:

由于业务逻辑,我的默认运算符是AND,因此,据我所知,搜索:

“ps3 slim 250gb new”

应返回包含该查询中每个单词的项目。我尝试切换到'或',但这会返回只有'new'或'slim'这个词的项目。

由于我们总是按日期排序而不是按相关性排序,因此这是一个很大的问题。所以'和'是。

这个想法是用很多同义词和停用词来解决这个问题。


第3。我的设置:

我目前的SOLR设置包含以下分析器链:

<fieldtype name="text_pt" class="solr.TextField" positionIncrementGap="100">
   <analyzer type="index">
       <tokenizer class="solr.WhitespaceTokenizerFactory"/>
       <filter class="solr.ASCIIFoldingFilterFactory" protected="protwords.txt"/>
       <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" 
            generateNumberParts="1" preserveOriginal="1" catenateWords="1" 
            catenateNumbers="1" catenateAll="0"/>
       <filter class="solr.LowerCaseFilterFactory"/>
       <filter class="solr.StopFilterFactory" ignoreCase="false" words="portugueseStopWords.txt"/>
       <filter class="solr.BrazilianStemFilterFactory"/>
       <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
   </analyzer>
   <analyzer type="query">
       <tokenizer class="solr.WhitespaceTokenizerFactory"/>
       <filter class="solr.ASCIIFoldingFilterFactory" protected="protwords.txt"/>
       <filter class="solr.SynonymFilterFactory" ignoreCase="true" synonyms="portugueseSynonyms.txt" 
                expand="true"/>
       <filter class="solr.StopFilterFactory" ignoreCase="true" words="portugueseStopWords.txt"/>
       <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" 
                catenateWords="1" preserveOriginal="1" catenateNumbers="1" catenateAll="0"/>
       <filter class="solr.LowerCaseFilterFactory"/>
       <filter class="solr.BrazilianStemFilterFactory"/>
       <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
   </analyzer>
</fieldtype>



4。问题:

我有同义词:

plaistation, plastation => playstation  #dirty spelling correction
ps3, playstation3  #just a synonym

第一个正常工作。 第二个导致同义词和WordDelimiter之间似乎存在冲突,如分析页面和&amp; debugQuery 中所示:

调试查询

<str name="querystring">title_search_pt:(ps3)</str>
<str name="parsedquery">MultiPhraseQuery(title_search_pt:"(ps3 ps) (3 playstation3 playstation) 3")</str>

查询分析器

WhitespaceTokenizerFactory => [pos:1] ps3
ASCIIFoldingFilterFactory  => [pos:1] ps3
SynonymFilterFactory       => [pos:1] ps3 
                              [pos:1] playstation3

StopFilterFactory          => [pos:1] ps3 
                              [pos:1] playstation3

WordDelimiterFilterFactory => [pos:1] ps3  [pos:2] 3              [pos:3] 3
                              [pos:1] ps   [pos:2] playstation3
                                           [pos:2] playstation


正如你所看到的那样,直到WordDelimiterFilter搞砸了它一切都很好。
我期待的是 ps playstation 在pos:1然后3在pos:2。
如果我将'OR'作为默认操作,这不会是一个问题,但由于我不可能,这将尝试匹配具有两个ps3和playstation3的文档,而不是给我更多的结果,它给我甚至少..


5。问题:

我该怎么办?我认为WordDelimiterFilter提供了许多好东西来完全删除它,但这种令牌位置转换对我来说并不合适。

3 个答案:

答案 0 :(得分:1)

我用一种讨厌的方式添加同义词解决了它,利用了这样的短语同义词的“限制”:

ps3 => playstation 3, ps 3
ps2 => playstation 2, ps 2

使用替换(=&gt;)和同义词(用逗号分隔的两个单词)是一种黑客攻击。

查询分析器如下所示:

WhitespaceTokenizerFactory => [pos:1] ps3
ASCIIFoldingFilterFactory  => [pos:1] ps3
SynonymFilterFactory       => [pos:1] ps            [pos:2] 3
                              [pos:1] playstation   [pos:2] 3

StopFilterFactory          => [pos:1] ps            [pos:2] 3
                              [pos:1] playstation   [pos:2] 3

WordDelimiterFilterFactory => [pos:1] ps            [pos:2] 3
                              [pos:1] playstation   [pos:2] 3
...
RemoveDuplicatesTokenFilterFactory =>  [pos:1] ps            [pos:2] 3
                                       [pos:1] playstation   

debugQuery

<str name="querystring">title_search_pt:(ps3 new)</str>
<str name="parsedquery">+MultiPhraseQuery(title_search_pt:"(playstation ps) 3") +title_search_pt:new</str>

我可以从同义词中删除3个中的一个,因为两个3将最终在同一个令牌位置,并将被RemoveDuplicatesTokenFilterFactory删除。但是我保持这样,所以我的同义词文件不那么神秘。

答案 1 :(得分:0)

您可以为WordDelimiterFilterFactory

设置属性splitOnNumerics="0"
  

splitOnNumerics =“1”导致alphabet =&gt;数字转换以生成新零件

     

“j2se”=&gt; “j”“2”“se”

     

默认为true(“1”);设置为0关闭

这应该消除它将ps3和playstation3分成两个令牌的问题,一个带有单词,一个带有数值。

答案 2 :(得分:0)

要完成答案:

你可以在protwords.txt文件中添加你在同义词中放入的所有单词(或者只有那些给你带来问题的单词),这样所有的标记器都会忽略它们并按原样对它们进行索引。

如果在同义词文件中使用它是有意义的,因为同义词是您想要找到的单词。