Solr Dismax处理程序 - 空格和特殊字符行为

时间:2011-10-25 10:21:12

标签: solr lucene tokenize dismax

当我的查询中有特殊字符时,我得到了奇怪的结果。

这是我的要求:

q=histoire-france&start=0&rows=10&sort=score+desc&defType=dismax&qf=any^1.0&mm=100%

解析查询:

<str name="parsedquery_toString">+((any:histoir any:franc)) ()</str>

我有17000个结果,因为Solr正在进行OR(应该是AND)。

当我使用空格而不是特殊字符时,我没有问题:

q=histoire france&start=0&rows=10&sort=score+desc&defType=dismax&qf=any^1.0&mm=100%

<str name="parsedquery_toString">+(((any:histoir) (any:franc))~2) ()</str>

此查询的2000个结果。

这是我的schema.xml(相关部分):

<fieldType name="text" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="false">
      <analyzer type="index">
        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
        <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1" preserveOriginal="1"/>
        <filter class="solr.LowerCaseFilterFactory"/>
        <filter class="solr.CommonGramsFilterFactory" words="stopwords_french.txt" ignoreCase="true"/>
        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords_french.txt" enablePositionIncrements="true"/>
        <filter class="solr.SnowballPorterFilterFactory" language="French" protected="protwords.txt"/>
        <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
        <filter class="solr.ASCIIFoldingFilterFactory"/>
      </analyzer>
      <analyzer type="query">
        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
        <!--<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>-->
        <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1" preserveOriginal="0"/>
        <filter class="solr.LowerCaseFilterFactory"/>
        <filter class="solr.CommonGramsFilterFactory" words="stopwords_french.txt" ignoreCase="true"/>
        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords_french.txt" enablePositionIncrements="true"/>
        <filter class="solr.SnowballPorterFilterFactory" language="French" protected="protwords.txt"/>
        <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
        <filter class="solr.ASCIIFoldingFilterFactory"/>
      </analyzer>
    </fieldType>

我甚至尝试使用PatternTokenizerFactory来标记空格和&amp;特殊的角色,但没有变化...

我目前的解决方法是在向Solr发送查询之前用空格替换所有特殊字符,但这并不令人满意。

编辑:即使用空格替换特殊字符的charFilter(PatternReplaceCharFilterFactory),它也不起作用......

第一行分析通过solr admin,详细输出,查询='histoire-france':

org.apache.solr.analysis.PatternReplaceCharFilterFactory {replacement= , pattern=([,;./\\'&-]), luceneMatchVersion=LUCENE_32}
text    histoire france

' - '替换为'',然后由WhitespaceTokenizerFactory标记。但是,对于'histoire-france'和'histoire france',我仍然有不同的结果。

我错过了什么吗?

4 个答案:

答案 0 :(得分:3)

您可以获得不同数量的搜索结果&#39; histoire-france&#39;并且&#39; histoire france&#39;因为查询解析器在第一种情况下创建一个短语查询,在第二种情况下创建一个布尔查询(分开两个单词)。

这不是明显的行为,但我相信很难满足所有用例。

进行搜索治疗&#39; histoire-france&#39;只需两个单词即可添加&#34; solr.PositionFilterFactory&#34;到查询分析器的末尾,如:

  <analyzer type="query">
    <tokenizer class="solr.StandardTokenizerFactory"/>
    <filter class="solr.LowerCaseFilterFactory"/>
    <filter class="solr.PositionFilterFactory" />
  </analyzer>

然后搜索&#39; histoire-france&#39;并且&#39; histoire france&#39;将是平等的。

请注意,短语搜索可能不需要位置过滤器(“历史记录”和“法国”都存在)。考虑使用查询slops参数qs&gt;如果您使用说NGram过滤器修改了术语序列,则为0。

答案 1 :(得分:1)

使用WhitespaceTokenizerFactory,Solr会将您的查询字符串拆分为单词。

但是,在标记后你(Solr)使用solr.WordDelimiterFilterFactory将你的单词(再次)分成两个词。查看文档并查看Wi-Fi示例。

这可能是一个原因,为什么histoire francehistoire-france的处理方式不同。

第二:不要忘记,DSIMAX(通常)将查询术语处理为“术语”,并且(另外)再次处理为解析后的字符串。

要解决您的问题,您可以尝试避免使用世界分隔符并尝试使用PatternTokenizerFactory处理“令牌化”(如您之前尝试过的那样,但现在没有使用WordDelimiterFilterFactory)。

如果不起作用,请尝试发布analysys.jsp的完整输出

答案 2 :(得分:1)

这是一个错误:https://issues.apache.org/jira/browse/SOLR-3589

  

如果其中一个令牌被分成两部分,则edismax mm设置为100%   分析仪链上的标记(即“fire-fly”=&gt; fire fly),mm   参数被忽略,相当于OR查询“fire OR fly”   被生产。对于没有的语言,这尤其是一个问题   使用空格分隔中文或日本语等词。

修正于Solr 4.1(2013年1月22日)

答案 3 :(得分:0)

启用autoGeneratePhraseQueries为true,这将生成短语查询 因此,当搜索histoire-franc时,它会生成一个带引号的查询,这将只启用将两个单词作为短语匹配的文档。

<str name="parsedquery">(+DisjunctionMaxQuery(((any:histoire any:franc))))/no_coord</str>

工作配置示例 -

<fieldType name="text_test" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true">
  <analyzer type="index">
    <tokenizer class="solr.WhitespaceTokenizerFactory"/>
    <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
    <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>
  <analyzer type="query">
    <tokenizer class="solr.WhitespaceTokenizerFactory"/>
    <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/>
    <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>
</fieldType>

使用查询slop指定slops的数量,例如短语查询中的qs=10

<str name="parsedquery">(+DisjunctionMaxQuery((any:"histoire france"~10)))/no_coord</str>