0

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

这是我的要求:

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)。

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

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 进行的第一行分析,带有详细输出,用于 ​​query = 'histoire-france' :

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

'-' 被 ' ' 替换,然后由 WhitespaceTokenizerFactory 标记。但是,对于“histoire-france”和“histoire France”,我仍然有不同数量的结果。

我错过了什么 ?

4

4 回答 4

3

搜索“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。

于 2012-02-06T18:28:25.353 回答
1

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

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

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

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

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

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

于 2011-10-25T15:02:35.790 回答
1

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

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

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

于 2013-01-24T09:38:42.763 回答
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>

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

<str name="parsedquery">(+DisjunctionMaxQuery((any:"histoire france"~10)))/no_coord</str>
于 2011-10-25T18:22:37.437 回答