当我在查询中使用特殊字符时,我得到了奇怪的结果。
这是我的请求:
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 france
和histoire-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>