Docs 菜单
Docs 主页
/ /

Sparse Indexes

稀疏索引仅包含具有索引字段的文档的条目,即使索引字段包含 null 值也是如此。该索引将跳过缺少索引字段的所有文档。索引是“稀疏”的,因为它不包括集合的所有文档。相比之下,非稀疏索引包含集合中的所有文档,为那些不包含索引字段的文档存储 null 值。

重要

部分索引可以用作稀疏索引,但也支持字段是否存在以外的条件的过滤表达式。如果需要精确筛选,请使用部分索引进行更好的控制。

要创建稀疏索引,请使用 db.collection.createIndex() 方法,并将 sparse 选项设置为 true

例如,mongosh 中的以下操作在 movies 集合的 plot 字段上创建稀疏索引:

db.movies.createIndex( { "plot": 1 }, { sparse: true } )

该索引不会索引不包含 plot 字段的文档。

注意

请勿将MongoDB中的稀疏索引与其他数据库中的区块级索引混淆。将它们视为具有特定过滤的密集索引。

如果稀疏索引会导致查询和排序操作的结果集不完整,则除非 hint() 显式指定该索引,否则 MongoDB 不会使用该索引。

例如,除非显式提示,否则查询 { plot: { $exists: false } } 不会在 plot 字段上使用稀疏索引。有关详细行为的示例,请参阅集合上的稀疏索引无法返回完整结果

当您对集合中所有文档执行 count() 时(即,采用空查询谓词),您要纳入指定稀疏索引hint(),即便该稀疏索引产生错误计数也要使用。

示例,在 movies集合的 rated字段上创建稀疏索引。

db.movies.createIndex( { rated: 1 }, { sparse: true } )

如果计算 movies集合中的文档数并包含指定该稀疏索引的提示,则该操作仅返回包含 rated字段的文档。

db.movies.countDocuments( {}, { hint: { rated: 1 } } )

要获得movies 集合中文档数量的正确计数,在对集合中的所有文档进行计数时,请勿使用稀疏索引hint()

db.movies.countDocuments()

以下索引类型始终是稀疏的:

复合索引可以包含不同类型的稀疏索引。索引类型的组合决定了复合索引与文档的匹配方式。

本表汇总了包含不同类型稀疏索引的复合索引的行为:

复合索引组件
复合索引行为
Ascending indexes
Descending indexes

仅对至少包含一个键值的文档进行索引。

Ascending indexes
Descending indexes

仅当文档包含一个 geospatial 字段的值时,才为文档编制索引。不在升序或降序索引中索引文档。

Ascending indexes
Descending indexes

仅当文档与一个 text 字段匹配时,才为文档编制索引。不在升序或降序索引中索引文档。

既稀疏又唯一的索引可防止集合的文档具有重复的字段值,但允许多个省略该键的文档。

以下示例在字段password 上创建稀疏索引:

db.users.createIndex( { password: 1 } , { sparse: true } )

然后,对 users集合的以下查询使用稀疏索引返回具有 password字段的文档:

db.users.find( { password: { $exists: true } } ).sort({ password: 1 }).limit(5)

如果用户不包含 password字段,则查询不会返回该用户。

考虑 movies集合,其中某些文档没有 plot字段。

以下示例在字段plot 上创建稀疏索引:

db.movies.createIndex( { "plot": 1 }, { sparse: true } )

以下查询返回 movies 集合中的所有文档(按 plot 字段排序):

db.movies.find().sort( { plot: -1 } )

即使按索引字段排序,如果movies 集合中的某些文档没有plot 字段, MongoDB也不会选择稀疏索引来完成查询以返回完整结果。

要使用稀疏索引,请用 hint() 显式指定该索引:

db.movies.find().sort( { plot: -1 } ).hint( { plot: 1 } ).limit(5)

此查询仅返回 movies集合中包含 plot字段的文档。

提示

以下操作在 中的 字段上创建具有唯一约束和稀疏过滤索引:passwordusers

db.users.createIndex( { password: 1 } , { sparse: true, unique: true } )

该索引允许插入具有唯一 password 字段值不包含 password 字段的文档。因此,鉴于 users 集合中的现有文档,该索引允许以下插入操作

db.users.insertMany( [
{ "name": "Jon Snow", "email": "jon@gameofthron.es", "password": "$2b$12$newHashedPassword1234567890ABC" },
{ "name": "Sansa Stark", "email": "sansa@gameofthron.es", "password": "$2b$12$anotherNewPassword1234567890DEF" },
{ "name": "Bran Stark", "email": "bran@gameofthron.es" }
] )

但是,该索引不允许添加包含集合中已存在的电子邮件地址的文档。

从 MongoDB 5.0 开始,具有相同键模式唯一稀疏唯一非稀疏索引可以存在于同一个集合中。

此示例将使用相同的键模式和不同的 sparse 选项来创建多个索引:

db.users.createIndex( { password : 1 }, { name: "unique_index", unique: true } )
db.users.createIndex( { password : 1 }, { name: "unique_sparse_index", unique: true, sparse: true } )

还可以使用和不使用稀疏选项创建具有相同键模式的基本索引:

db.users.createIndex( { password : 1 }, { name: "sparse_index", sparse: true } )
db.users.createIndex( { password : 1 }, { name: "basic_index" } )

后退

部分

在此页面上