当我的查询中有特殊字符时,我得到了奇怪的结果。
这是我的要求:
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',我仍然有不同的结果。
我错过了什么吗?
答案 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 france
和histoire-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>