OPTIONS
翻译或纠错本页面

稀疏索引

稀疏索引中值存储那些有被索引键的文档的索引项,即使被索引键的值是null也会被索引(译者注:请注意,这里对null的处理和那些特殊索引的默认稀疏特性有细微差别,比如文本索引,2d索引等)。索引会跳过所有不包含被索引键的文档。这个索引之所以称为 “稀疏” 是因为它并不包括集合中的所有文档。与之相反,非稀疏的索引会索引每一篇文档,如果一篇文档不含被索引键则为它存储一个null值。

如果希望创建一个 稀疏 索引, 请在 db.collection.ensureIndex() 方法中将 sparse 选项设为 true 。例如,在 mongo shell中执行如下操作可以在 addresses 集合的 xmpp_id 键上建立一个稀疏索引:

db.addresses.ensureIndex( { "xmpp_id": 1 }, { sparse: true } )

注解

不要把MongoDB中的稀疏索引和其他数据库中的 block-level 索引相混淆了。把它们看作带有特殊过滤器的密集索引。

特性

关于 稀疏 索引和不完整结果

在 2.6 版更改.

如果一个索引会导致查询或者排序的结果集是不完整的,那么MongoDB将不会使用这个索引,除非用户使用 hint() 方法来显示指定索引。

例如,查询 { x: { $exists: false } } 将不会使用 x 键上的稀疏索引,除非显示的hint。参见 在A集合上的稀疏索引不会返回完整结果 来了解有关这个特性的具体例子。

默认是 稀疏 的索引

2dsphere (version 2), 2d, geoHaystack, 和 text 这些索引总是 稀疏 的(译者注:请注意,这些索引对null的处理和这里的稀疏索引的处理有细微差别,不要混淆了!)。

稀疏 复合索引

只要一篇文档里有至少一个被索引键,稀疏且只包含有递增/递减索引键的 复合索引 就会索引这篇文档。

至于稀疏且包含有地理索引键 (例如 2dsphere, 2d, 或者 geoHaystack ) 以及递增/递减索引键的复合索引,只有地理索引键的存在与否能决定一篇文档是否被索引。

至于稀疏且包含了 文本 索引键和其他递增/递减索引键的复合索引,只有 文本 索引键的存在与否能决定是否索引该文档。

稀疏唯一 属性

一个 稀疏唯一 的索引,可以防止集合中的文档被索引键中出现重复值,同时也允许多个文档里不包含被索引键。

例子

在A集合上创建稀疏索引

假设集合 scores 有如下文档:

{ "_id" : ObjectId("523b6e32fb408eea0eec2647"), "userid" : "newbie" }
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }
{ "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }

集合在 score 键上有一个稀疏索引:

db.scores.ensureIndex( { score: 1 } , { sparse: true } )

那么,在 scores 集合上执行如下查询,将会利用稀疏索引来返回包含了 score 键且值小于 ($lt) 90 的文档:

db.scores.find( { score: { $lt: 90 } } )

由于userid为 "newbie" 的文档不包含 score 键,因此无法满足查询条件,那么查询可以利用稀疏索引来返回如下结果:

{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }

在A集合上的稀疏索引不会返回完整结果

假设集合 scores 有如下文档:

{ "_id" : ObjectId("523b6e32fb408eea0eec2647"), "userid" : "newbie" }
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }
{ "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }

集合在 score 键上有一个稀疏索引:

db.scores.ensureIndex( { score: 1 } , { sparse: true } )

由于userid为 "newbie" 的文档不包含 score 键, 因此稀疏索引中不包含该文档的索引项。

假设有如下查询,返回 scores 集合中 所有 文档并按照 score 键排序:

db.scores.find().sort( { score: -1 } )

即使是按照被索引键排序,MongoDB仍然 不会 选择稀疏索引来匹配这个查询,这是为了可以得到完整的结果集:

{ "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }
{ "_id" : ObjectId("523b6e32fb408eea0eec2647"), "userid" : "newbie" }

如果希望使用稀疏索引,请在 hint() 显示指定该索引:

db.scores.find().sort( { score: -1 } ).hint( { score: 1 } )

(稀疏)索引的使用导致了只有那些包含 score 键的文档被返回了:

{ "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }

稀疏索引和唯一性限制

假设集合 scores 有如下文档:

{ "_id" : ObjectId("523b6e32fb408eea0eec2647"), "userid" : "newbie" }
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }
{ "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }

您可以通过如下操作在 score 键上创建一个同时拥有 唯一性限制 和稀疏过滤的索引:

db.scores.ensureIndex( { score: 1 } , { sparse: true, unique: true } )

这个索引 允许 插入 score 键上的值是唯一或者不包含 score 键的文档。有如下 插入 :

db.scores.insert( { "userid": "AAAAAAA", "score": 43 } )
db.scores.insert( { "userid": "BBBBBBB", "score": 34 } )
db.scores.insert( { "userid": "CCCCCCC" } )
db.scores.insert( { "userid": "DDDDDDD" } )

但是,这个索引 不允许 添加如下文档,因为 score 键上值为 8290 的文档已经存在了:

db.scores.insert( { "userid": "AAAAAAA", "score": 82 } )
db.scores.insert( { "userid": "BBBBBBB", "score": 90 } )
←   唯一索引 索引创建  →