【问题标题】:Solr Dismax handler - whitespace and special character behaviourSolr Dismax 处理程序 - 空格和特殊字符行为
【发布时间】:2011-10-25 10:21:12
【问题描述】:

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

这是我的要求:

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 对空格和特殊字符进行标记,但没有改变...

我目前的解决方法是在向 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”,我仍然有不同数量的结果。

我错过了什么吗?

【问题讨论】:

  • 从 WhiteSpaceTOckenizer 更改为 PatternTokenizer 后,您是否重新索引数据?您需要重新索引数据以查看任何更改
  • 你说你有 你能把它改成 重启 SOLR 并分享每个查询的结果数。如果我的猜测是真的,我稍后会给你更详细的解释。
  • 我更改了 defaultOperator 并重新启动了 solr。不用找了。无论如何,我认为 Dismax 处理程序正在使用“mm”(最小匹配)参数而不是默认运算符。这里我的 mm=100% 与默认处理程序的 defaultOperator="AND" 相同。
  • 如果我使用 mm=0% (defaultOperator="OR") 每个查询都有 17000 个结果
  • 我认为 DISMAX 在构建查询时并不关心 defaultOperator,它将“histoire-france”视为一个单词,将“histoire france”视为两个单独的单词。抱歉,我帮不上忙。

标签: solr lucene tokenize dismax


【解决方案1】:

搜索“histoire-france”和“histoire france”会得到不同数量的结果,因为查询解析器在第一种情况下创建一个短语查询,在第二种情况下创建一个布尔查询(分隔两个词)。

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

要使搜索将“histoire-france”简单地视为两个词,您可以在查询分析器的末尾添加“solr.PositionFilterFactory”,例如:

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

那么“histoire-france”和“histoire france”的搜索结果将相等。

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

【讨论】:

    【解决方案2】:

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

    但是,在对你(Solr)进行标记之后,使用solr.WordDelimiterFilterFactory 将你的单词(再次)拆分为术语。查看文档并查看 Wi-Fi 示例。

    这可能是histoire francehistoire-france 处理方式不同的原因之一。

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

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

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

    【讨论】:

      【解决方案3】:

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

      如果其中一个标记被分成两个,则 edismax mm 设置为 100% 分析器链的标记(即“萤火虫”=> 萤火虫),mm 参数被忽略,相当于“fire OR fly”的 OR 查询 被生产。对于不支持的语言来说,这尤其是一个问题。 使用空格分隔中文或日语等单词。

      它已在 Solr 4.1(2013 年 1 月 22 日)中修复

      【讨论】:

        【解决方案4】:

        将 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>
        

        使用查询斜率来指定斜率的数量,例如qs=10 在短语查询中。

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

        【讨论】:

        • 如果我添加 autoGeneratePhraseQueries,则会为“france-histoire”生成短语查询,但不会为“france histoire”生成短语查询。假设我有一份包含“histoire de la france”的文档。那么短语“france-histoire”将不匹配......
        • 使用查询斜率。更新了答案。
        猜你喜欢
        • 2014-11-16
        • 1970-01-01
        • 2013-04-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-22
        • 1970-01-01
        相关资源
        最近更新 更多