翻译或纠错本页面

稀疏索引

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

重要

在 3.2 版更改: Starting in MongoDB 3.2, MongoDB provides the option to create partial indexes. Partial indexes offer a superset of the functionality of sparse indexes. If you are using MongoDB 3.2 or later, partial indexes should be preferred over sparse indexes.

Create a Sparse Index

To create a sparse index, use the db.collection.createIndex() method with the sparse option set to true. For example, the following operation in the mongo shell creates a sparse index on the xmpp_id field of the addresses collection:

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

The index does not index documents that do not include the xmpp_id field.

注解

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

Behavior

sparse Index and Incomplete Results

在 2.6 版更改.

If a sparse index would result in an incomplete result set for queries and sort operations, MongoDB will not use that index unless a hint() explicitly specifies the index.

For example, the query { x: { $exists: false } } will not use a sparse index on the x field unless explicitly hinted. See 在A集合上的稀疏索引不会返回完整结果 for an example that details the behavior.

Indexes that are sparse by Default

2dsphere (version 2), 2d, geoHaystack, and text indexes are always sparse.

sparse Compound Indexes

Sparse compound indexes that only contain ascending/descending index keys will index a document as long as the document contains at least one of the keys.

For sparse compound indexes that contain a geospatial key (i.e. 2dsphere, 2d, or geoHaystack index keys) along with ascending/descending index key(s), only the existence of the geospatial field(s) in a document determine whether the index references the document.

For sparse compound indexes that contain text index keys along with ascending/descending index keys, only the existence of the text index field(s) determine whether the index references a document.

sparse and unique Properties

An index that is both sparse and unique prevents collection from having documents with duplicate values for a field but allows multiple documents that omit the key.

例子

在A集合上创建稀疏索引

Consider a collection scores that contains the following documents:

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

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

db.scores.createIndex( { 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集合上的稀疏索引不会返回完整结果

Consider a collection scores that contains the following documents:

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

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

db.scores.createIndex( { 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 }

稀疏索引和唯一性限制

Consider a collection scores that contains the following documents:

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

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

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

This index would permit the insertion of documents that had unique values for the score field or did not include a score field. As such, given the existing documents in the scores collection, the index permits the following insert operations:

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 } )