在本页面
Sparse索引只包含有索引字段的文档的条目,即使索引字段包含空值。索引会跳过任何缺少索引字段的文档。索引是**“稀疏的”**,因为它不包括一个集合的所有文档。相反,非稀疏索引包含集合中的所有文档,为那些不包含索引字段的文档存储空值。
重要的
从MongoDB 3.2开始,MongoDB提供了创建的选项。部分索引提供了sparse索引功能的超集。如果你正在使用MongoDB 3.2或更高版本,应该比稀疏索引更受欢迎。
创建sparse索引
要创建一个**“sparse”索引,使用方法,并将“sparse”选项设置为“true”。例如,下面的操作在 shell中创建了一个稀疏的索引在xmpp_id**字段的地址集合:
db.addresses.createIndex( { "xmpp_id": 1 }, { sparse: true } )
索引不会索引不包含**“xmpp_id”**字段的文档。
注意
不要将MongoDB中的sparse索引与其他数据库中的索引混淆。可以将它们看作具有特定过滤器的密集索引。
行为
“Sparse”索引和不完整结果
Changed in version 3.4.
db.collection.insert({ _id: 1, y: 1 } );
db.collection.createIndex( { x: 1 }, { sparse: true } );
db.collection.find().hint( { x: 1 } ).count();
db.collection.find().count();
db.collection.createIndex({ y: 1 });
db.collection.find().hint({ y: 1 }).count();
默认情况下是“sparse”的索引
Sparse复合索引
“Sparse”和“unique”属性
例子
在集合上创建sparse索引
考虑一个包含以下文档的集合**“scores”**:
{ "_id" : ObjectId("523b6e32fb408eea0eec2647"), "userid" : "newbie" }
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }
{ "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }
集合在**“score”字段上有一个sparse**索引:
db.scores.createIndex( { score: 1 } , { sparse: true } )
db.scores.find( { score: { $lt: 90 } } )
由于userid的文档"newbie"
不包含该 score
字段,因此不满足查询条件,因此查询可以使用sparse索引返回结果:
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }
集合上的sparse索引不能返回完整的结果
考虑一个包含以下文档的集合“scores”:
{ "_id" : ObjectId("523b6e32fb408eea0eec2647"), "userid" : "newbie" }
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }
{ "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }
集合在**“score”**字段上有一个sparse索引:
db.scores.createIndex( { score: 1 } , { sparse: true } )
因为userid的文档 "newbie"
不包含score
字段,所以sparse索引不包含该文档的条目。
考虑以下查询返回scores
集合中的所有文档,按score
字段排序:
db.scores.find().sort( { score: -1 } )
即使是按索引字段排序,MongoDB也不会选择sparse索引来完成查询,以返回完整的结果:
{ "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }
{ "_id" : ObjectId("523b6e32fb408eea0eec2647"), "userid" : "newbie" }
要使用sparse索引,显式地用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 }
也可以看看:
具有唯一约束的sparse索引
考虑一个包含以下文档的集合scores:
{ "_id" : ObjectId("523b6e32fb408eea0eec2647"), "userid" : "newbie" }
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }
{ "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }
db.scores.createIndex( { score: 1 } , { sparse: true, unique: true } )
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值为82和90:
db.scores.insert( { "userid": "AAAAAAA", "score": 82 } )
db.scores.insert( { "userid": "BBBBBBB", "score": 90 } )