是否有理由只使用 ngrams 字段进行搜索?我不确定这是否是您的问题,但您可能想查看 schema.xml 中的 ngrams 分析配置。我的一个索引中的一个如下所示:
<fieldType name="ngram" class="solr.TextField" >
<analyzer type="index">
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
<tokenizer class="solr.LowerCaseTokenizerFactory"/>
<filter class="solr.EdgeNGramFilterFactory" minGramSize="2" maxGramSize="15" side="front"/>
</analyzer>
<analyzer type="query">
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
<tokenizer class="solr.LowerCaseTokenizerFactory"/>
</analyzer>
</fieldType>
虽然您可以看到这实际上是使用更安全EdgeNGramFilterFactory
的,但这里需要注意的重要一点是minGramSize="2"
。这意味着在索引过程中只会创建至少两个字符的克。“c”这个词?那根本没有任何克数。虽然您可以设置minGramSize="1"
和重建索引,但单字符grams 是一个非常糟糕的主意,因为您对“c”的搜索将匹配任何以“c”开头的单词(或包含带有“c”的字母NGramFilterFactory
)的文档。
如果您当前使用带有 的 NGrams minGramSize="2"
,则搜索“ca”将找到任何包含按该顺序连续包含字母“ca”的单词的任何文档。这也可能不是您想要的。
我的首要建议是放弃 ngram 以支持更普通的文本字段。是否要保留 edge-ngrams 以获得更好的截断支持取决于您,但我怀疑如果 Text 字段至少在混合中,您会有更好的运气。
您还可以查看 StackOverflow 上的这个问题:“我可以在 Solr 中保护短词免受 n-gram 过滤器的影响吗?” 如果您想进一步研究 ngram。
此外,您应该考虑使用 Solr 的内置分析工具来找出您的搜索失败的地方。您选择一个字段或字段类型,并为输入到索引中的内容和正在搜索的内容提供值。它将向您展示分析如何针对这两个值进行,因此您可以了解每个字符串是如何分解的,以及它为什么会创建或不创建匹配的标记。该工具的 URL 取决于您是否处于多核环境中,但如果您访问 Solr 的 Web 界面,您应该能够Analysis
在左侧找到该链接。
更新:
现在我从你那里得到了更多的细节并且正在再次考虑它,你得到的结果是非常可以解释的。
使用minGramSize="1"
,您对 'vitamin c' 的未引用搜索正在查找包含单词 'vitamin'(或包含 'vitamin' 的更长单词)和单词 'c'(或包含 'c' 的更长单词)的记录。由于大多数记录可能在某处有一个“c”,这几乎不是一个限制因素,您的结果将非常接近或与您仅使用“维生素”一词的结果非常接近或完全相同。
在引用的“维生素 c”搜索中,“c”现在必须出现在维生素之后的单词中,这使其成为更有用的搜索,但仍然不是很好。您应该能够通过查找在维生素后面有一个不是维生素名称的单词的记录来测试这一点。例如,在搜索“vitamin b”时应该找到一条提及“vitamin tablet”的记录(因为“tablets”中有一个“b”)。并且在搜索“维生素c”时,应找到提及“维生素图表”或“维生素缺乏症”的记录。
这样做的结果是,我强烈建议将一组用于搜索的字段与自动完成的字段分开。带有的 NGramminGramSize="1"
不会为您提供实际搜索步骤的合理结果。