倒排索引

前言

Elasticsearch使用了一种叫做倒排索引的结构,一种设计用来允许快速全文检索的。一个倒排索引包含出现在任何文档中的所有的唯一词的列表,以及对于每个词,他们在哪些文档中出现的列表。

举例

举个例子,比如说我们有两个文档,每一个都有一个content属性包含下列内容:
The quick brown fox jumped over the lazy dog
Quick brown foxes leap over lazy dogs in summer

要创建一个倒排索引,我们首先要把每个文档中的content属性中的内容分割成分开的词(我们叫做terms,或者tokens)。创建一个包含所有唯一词并排好序的列表,并且列出每一个词在哪些文档中有出现。结果看起来是这样的:

现在,如果你想查询quick brown,我们只需要找出每个词在哪些文档中出现就可以了。

两个文档都匹配,但是第一个文档比第二个文档有更多匹配。如果我们加入简单的相似度算法,仅用来计算匹配词的数量。然后我们就可以说第一个文档更匹配,比我们的第二个文档更接近我们的查询。

但是当前我们的倒排索引有一些问题:

  1. Quick和quick作为不同的词出现,但是用户可能认为他们是一个词
  2. fox 和foxes是很相似的,同样的dog和dogs,他们是同根词。
  3. jumped和leap虽然他们不是同根词,但是在意思上是相近的。他们是同义词。

在上述的索引中,搜索+Quick +fox将不会匹配任何文档(记住,前缀+意味着词必须完全匹配)。只有Quick和fox在同一个文档中出现的时候才会出现令人满意的查询了,但是第一个文档包含了quick fox,第二个文档包含了Quick foxes.
我们的用户可能希望两个文档都能匹配查询,我们可以做的更好。

如果我们将词格式化成标准的格式,然后我们发现文档包含的词和用户请求的词不是完全匹配的,但是仍然足够相似找到文档。举个例子:

  1. Quick可以被小写成quick
  2. foxes可以取他的根fox,同样的dogs也可以取根dog
  3. jumped和leap是同义词可以索引成单一词jump

现在索引看起来应该是这样的:

但是我们还没有完成。我们搜索+Quick +fox可能仍然失败,因为我们不再有精确的词Quick在我们的索引中。这样如果我们用同样的规则在我们的查询字段content上,查询应该变成+quick +fox, 这样就可以匹配两个文档了。
注意:这很重要。你只可以找到那些在你的索引中存在的词,因此索引的文本和查询的字符串必须格式化成同样的形式。