使用短语与带状疱疹之间的差异主要涉及性能和评分。
在索引中单个单词的典型情况下使用短语查询(例如“foo bar”)时,短语查询必须遍历“foo”和“bar”的倒排索引并查找包含这两个术语的文档,然后在每个文档中遍历它们的位置列表以查找“foo”出现在“bar”之前的位置。
这对性能和评分都有一些影响:
- 位置(.prx)必须索引和搜索,这就像倒排索引的额外“维度”,这将增加索引和搜索时间
- 由于倒排索引中仅显示单个术语,因此没有计算出真正的“短语 IDF”(这可能不会影响您)。因此,这是基于术语IDF的总和的近似值。
另一方面,如果您使用带状疱疹,则还会索引单词n-grams,换句话说,如果您要瓦化到大小2,则索引中还将具有诸如“foo bar”之类的术语。这意味着对于此短语查询,它将被解析为简单的 TermQuery,而不使用任何位置列表。由于IDF现在是一个“实际术语”,因此短语IDF将是准确的,因为我们确切地知道这个“术语”存在多少文件。
但是使用带状疱疹也有一些成本:
- 增加了术语字典,术语索引和帖子列表大小,尽管这可能是一个公平的权衡,特别是如果您使用Field.setIndexOptions完全禁用头寸。
- 在索引的分析阶段有一些额外的成本:尽管ShigleFilter优化得很好,而且速度非常快。
- 没有明显的方法来计算“草率的短语查询”或不精确的短语匹配,尽管这可以近似,例如,对于大小为2的带状疱疹的“foo bar baz”短语,您将有两个标记:foo_bar,bar_baz,您可以通过Lucene的其他一些查询(如BooleanQuery)实现搜索,以获得不精确的近似值。
一般来说,使用带状疱疹或CommonGrams之类的东西索引单词ngram只是一种权衡(相当专业),以降低位置查询的成本或提高短语评分。
但是这些东西有现实世界的用例,这里有一个很好的例子:http://www.hathitrust.org/blogs/large-scale-search/slow-queries-and-common-words-part-2