Solr 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正在做一个或(应该是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发送查询之前将所有特殊字符替换为空白,但这并不令人满意。

EDIT:即使使用charFilter (PatternReplaceCharFilterFactory)用空格替换特殊字符,它也不起作用…

通过solr admin进行的第一行分析,带有详细输出,查询= ' history -france':

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

将'-'替换为' ',然后使用WhitespaceTokenizerFactory进行标记化。然而,"histoire-france"one_answers"histoire france"的结果数量仍然不同。

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

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

要使搜索将"history -france"作为简单的两个单词,您可以添加"solr"。PositionFilterFactory"到查询分析器的末尾,如:

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

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

注意,对于短语搜索,位置过滤器可能不需要(' history '和'france'都存在)。如果您使用NGram过滤器修改了术语序列,请考虑使用查询斜率参数qs> 0。

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

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

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

第二:不要忘记,DSIMAX(通常)将查询项处理为"term",并且(额外)再次处理为已解析的字符串。

要解决您的问题,您可以尝试避免世界分隔符,并尝试通过使用PatternTokenizerFactory来处理"标记化"(就像您之前尝试的那样,但现在没有WordDelimiterFilterFactory)。

如果这不起作用,尝试发布analysys.jsp

的完整输出。

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

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

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

启用autoGeneratePhraseQueries为true,这将生成短语查询。
因此,当搜索history -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来指定slop的个数,例如在短语查询中qs=10

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

最新更新