我遇到Solr问题。我想让它在搜索查询中连接单词。例如,我希望能够搜索“数据链接”并使其包含一个包含“datalink”的文档(Google会这样做 - 所以为什么Solr会这么困难?)。
以下是schema.xml的索引和查询分析器设置:
<fieldType name="text_en_splitting" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true">
<analyzer type="index">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="lang/stopwords_en.txt"
/>
<filter class="solr.WordDelimiterFilterFactory"
generateWordParts="1"
generateNumberParts="1"
catenateWords="0"
catenateNumbers="0"
catenateAll="0"
splitOnCaseChange="1"
/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
<filter class="solr.PorterStemFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.SynonymFilterFactory"
synonyms="synonyms.txt"
ignoreCase="true"
expand="true"
/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="lang/stopwords_en.txt"
/>
<filter class="solr.WordDelimiterFilterFactory"
generateWordParts="1"
generateNumberParts="1"
catenateWords="1"
catenateNumbers="0"
catenateAll="0"
splitOnCaseChange="1"
/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
<filter class="solr.PorterStemFilterFactory"/>
</analyzer>
</fieldType>
当我搜索“数据链接”时,这是debugQuery的输出:
"rawquerystring": "\"data link\"\n",
"querystring": "\"data link\"\n",
"parsedquery": "PhraseQuery(text:\"data link\")",
"parsedquery_toString": "text:\"data link\"",
当我搜索“data-link”时,这是debugQuery的输出 - 这也没有点击“datalink”,即使它似乎存在于MultiPhraseQuery中?有人可以解释一下吗?
"rawquerystring": "\"data-link\"\n",
"querystring": "\"data-link\"\n",
"parsedquery": "MultiPhraseQuery(text:\"(data datalink) link\")",
"parsedquery_toString": "text:\"(data datalink) link\"",
答案 0 :(得分:1)
这是非常复杂的理由,但这里发生的大部分内容似乎都是由于WordDelimiterFilter及其参数generateWordParts
和concatentateWords
。在索引中,您正在生成部分,但不会连接,但在查询中,您同时执行这两项操作。
索引时
WordDelimiterFilter
并不是第二次猜测已经是两个单独的单词。generateWordParts
,因此会将其编入索引为&#34;数据链接&#34;。搜索时
&#34; 数据链接&#34;&#34;:这是两个单独的字词,就像在索引时一样,查询时间WordDelimiterFilter
没有&改变这一点。它还有两个字。
&#34; 数据链接&#34;:搜索分析的配置与索引分析不同,因此将其搜索为&#34;数据链接&#34 ;和&#34;数据链接&#34;。
结果?
您搜索&#34;数据链接&#34;会搜索术语&#34; datalink&#34;,但您要编制索引的值只会被索引为&#34; datalink&#34;如果它们是首先以这种方式编写的,因为在编制索引时你永远不会激活concatenateWords
。
您可以选择做的一件事是选择concatenateWords
或 generateWordParts
,并在索引和搜索时激活字段中的一个或另一个。我选择的另一个选项是在<copyField/>
中使用schema.xml
来复制生成单词部分的字段和单词连接的字段之间的值。至少,我发现尝试在单个字段中进行连接和部分操作会对短语搜索造成严重破坏,因为当术语无法清楚计算时,单个术语的位置编号就会失控。
但是,如果您希望在搜索数据链接时找到可以找到 datalink 一词的文档,那么WordDelimiterFilter
赢了&#39 ; t help,因为它永远不会将数据链接视为两个单词的候选者,或数据链接作为单个单词的候选者。它的专长在于连字符和撇号之类的模糊环境。
相反,您可能需要构建自己的逻辑查询。 (逻辑运算符在标准/ Lucene查询处理程序和Extended-Dismax查询处理程序中工作,但不在Dismax查询处理程序中工作。)这种查询可能很快变得复杂,但(+data +link) OR datalink
之类的东西是一个很好的第一步。如果包含三个术语,则很难知道可能会连接哪个术语,因此像datalinkcisco OR (+datalink +cisco) OR (+data +linkcisco) OR (+data +link +cisco)
这样的查询可能会开始发挥作用。 (想象一下有四个术语!)
这非常复杂,非常快,如果只有少数几个术语可以在某些时候连接,你可以试试SynonymFilter
。这允许使用以下规则建立同义词文件:
data link => datalink
所以&#34;数据链接的所有实例&#34>将被编入索引或查询(如配置)为&#34;数据链接&#34;代替。这可以规范化特定的搜索术语,而无需打开我们不信任用户知道空间所属的蠕虫。
SynonymFilter
对其他事情有好处。例如,如果您从搜索索引中过滤标点符号,&#34; C ++&#34;和&#34; C&#34;可能最终看起来相当于Solr。使用同义词规则:
C++ => cplusplus
这最终完全不同。 (当然,没有真人会搜索cplusplus,但是如果您在用户查询中的索引文档和中应用相同的转换为&#34; C ++&#34; ,那么他们永远不必知道&#34; cplusplus&#34;是实际进行比赛的价值。)
答案 1 :(得分:0)
要允许data link
和datalink
匹配,您必须将ShingleFilter
添加到索引器和查询链中:
您可以将其与WordDelimiterFilter
。
要减少生成但可能无用的令牌数量,您可以添加LengthFilter
min=2
和一些合理的最大值。例如,WDF可以生成来自&#34; iPhone6s&#34;&#34; i&#34;,&#34; Phone&#34;,&#34; 6&#34;,&#34; s&#34 ; (以及更多取决于配置)。
此外,RemoveDuplicateTokensFilter
可以在该链中最后添加: