我对 Lucene 的理解还很陌生,但我知道
StringField
是索引的但不是标记化的,因此原始字符串“按原样”存储而不是被分解。这是否意味着 Lucene 在索引 StringField 时实际上会忽略正在使用的任何分析器?
看起来
KeywordAnalyzer
执行与 StringField 相同的功能,即它存储原始文本而不是对其进行标记。你什么时候会使用其中一种而不是另一种?当您可以只使用 StringField 时,使用(例如)TextField + KeywordAnalyzer 似乎很奇怪。
这是否意味着 Lucene 在索引
StringField
时实际上会忽略正在使用的任何分析器?
是的,这是正确的。
KeywordAnalyzer
和 StringField
:您什么时候会使用其中一种而不是另一种?
我知道需要
KeywordAnalyzer
的最常见场景是执行搜索时,而不一定是索引时。在这种情况下,它不是“使用一个而不是另一个” - 它更多是关于需要使用KeywordAnalyzer
,因为你选择如何使用StringField
。
考虑以下场景:
您有一个名为
StringField
的 postal_code
,用于自然包含空格的数据 - 例如 SW1A 1AA
等值。您想保留这些空间。
索引后,该字段包含未标记化的值(不是
SW1A
和 1AA
,而只是 SW1A 1AA
)。我们假设还有其他字段使用标准分析器和 TextField
字段以更传统的方式进行标记。
现在您想要搜索您的数据。
假设您要搜索该
postal_code
字段。它必须是“精确”搜索,因为数据未标记化。我们暂时忽略大小写问题。
如果您尝试搜索postal_code:"SW1A 1AA"
,您的查询将失败。至少在 Java 中,它实际上会抛出运行时错误。我认为 Lucene .Net 也是如此。
这是因为您使用了包含"SW1A 1AA"
的查询,这是一个
phrase- 双引号中包含的值。 短语需要在索引中创建位置数据,以便 Lucene 知道它需要找到紧随其后的标记
SW1A
。但是,名为
1AA
的 StringField
不会生成任何此类位置数据(与常规 postal_code
字段不同)。因此,您可以在搜索时使用 TextField
来搜索 此特定字段- 您的搜索将按预期进行。
这个例子可能看起来有点做作——我不会不同意。在 Lucene 中,通常可以有不止一种方法来获得您想要的东西。您更有可能使用KeywordAnalyzer
并确保在索引数据之前以某种方式清理数据 - 例如,从邮政编码中删除空格;或从信用卡号中删除连字符,等等...
只是为了跟进有关位置数据的这一点:默认情况下,文本字段不仅对数据进行标记,而且还捕获原始文本中每个标记的位置 - 从而实现一系列不同类型的查询。一个例子是邻近搜索。
搜索中的短语StringField
只是一种特定类型的邻近搜索。