聚合使用一个叫 doc values 的数据结构(在 Doc Values 介绍 里简单介绍)。 Doc values 可使聚合更快、更高效而且内存友好,因此理解它的工做方式十分有益。html
Doc values 的存在是由于倒排索引只对某些操做是高效的。 倒排索引的优点 在于查找包含某个项的文档,而对于从另一个方向的相反操做并不高效,即:肯定哪些项是否存在单个文档里,聚合须要这种次级的访问模式。数据结构
对于如下倒排索引:elasticsearch
Term Doc_1 Doc_2 Doc_3 ------------------------------------ brown | X | X | dog | X | | X dogs | | X | X fox | X | | X foxes | | X | in | | X | jumped | X | | X lazy | X | X | leap | | X | over | X | X | X quick | X | X | X summer | | X | the | X | | X ------------------------------------
若是咱们想要得到全部包含 brown
的文档的词的完整列表,咱们会建立以下查询:ide
GET /my_index/_search { "query" : { "match" : { "body" : "brown" } }, "aggs" : { "popular_terms": { "terms" : { "field" : "body" } } } }
查询部分简单又高效。倒排索引是根据项来排序的,因此咱们首先在词项列表中找到 brown
,而后扫描全部列,找到包含 brown
的文档。咱们能够快速看到 Doc_1
和 Doc_2
包含 brown
这个 token。ui
而后,对于聚合部分,咱们须要找到 Doc_1
和 Doc_2
里全部惟一的词项。 用倒排索引作这件事情代价很高: 咱们会迭代索引里的每一个词项并收集 Doc_1
和 Doc_2
列里面 token。这很慢并且难以扩展:随着词项和文档的数量增长,执行时间也会增长。code
Doc values 经过转置二者间的关系来解决这个问题。倒排索引将词项映射到包含它们的文档,doc values 将文档映射到它们包含的词项:htm
Doc Terms ----------------------------------------------------------------- Doc_1 | brown, dog, fox, jumped, lazy, over, quick, the Doc_2 | brown, dogs, foxes, in, lazy, leap, over, quick, summer Doc_3 | dog, dogs, fox, jumped, over, quick, the -----------------------------------------------------------------
当数据被转置以后,想要收集到 Doc_1
和 Doc_2
的惟一 token 会很是容易。得到每一个文档行,获取全部的词项,而后求两个集合的并集。排序
所以,搜索和聚合是相互紧密缠绕的。搜索使用倒排索引查找文档,聚合操做收集和聚合 doc values 里的数据。索引
Doc values 不只能够用于聚合。 任何须要查找某个文档包含的值的操做都必须使用它。 除了聚合,还包括排序,访问字段值的脚本,父子关系处理(参见 父-子关系文档 )。token