Section 9.1: 创建索引基础知识
请参阅下面的事务集合。
> db.transactions.insert({ cr_dr : "D", amount : 100, fee : 2});
> db.transactions.insert({ cr_dr : "C", amount : 100, fee : 2});
> db.transactions.insert({ cr_dr : "C", amount : 10, fee : 2});
> db.transactions.insert({ cr_dr : "D", amount : 100, fee : 4});
> db.transactions.insert({ cr_dr : "D", amount : 10, fee : 2});
> db.transactions.insert({ cr_dr : "C", amount : 10, fee : 4});
> db.transactions.insert({ cr_dr : "D", amount : 100, fee : 2});
getIndexes() 函数将显示一个集合的所有可用索引。
db.transactions.getIndexes();
让我们看看上述语句的输出结果。
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "documentation_db.transactions"
}
]
事务集合已有一个索引。这是因为 MongoDB 在创建集合时会在 _id 字段上创建唯一索引。_id 索引可防止客户端插入两个_id字段值相同的文档。您不能在 _id 字段上删除该索引。
现在,让我们为 cr_dr 字段添加一个索引;
db.transactions.createIndex({ cr_dr : 1 });
执行索引的结果如下。
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
createdCollectionAutomatically 表示操作是否创建了一个集合。如果不存在集合,MongoDB 会在索引操作中创建集合。
让我们再次运行 db.transactions.getIndexes();。
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "documentation_db.transactions"
},
{
"v" : 1,
"key" : {
"cr_dr" : 1
},
"name" : "cr_dr_1",
"ns" : "documentation_db.transactions"
}
]
现在你可以看到事务集合有两个索引。默认的 _id 索引和我们创建的 cr_dr_1。名称由 MongoDB 指定。你可以像下面这样设置自己的名称。
db.transactions.createIndex({ cr_dr : -1 },{name : "index on cr_dr desc"})
现在,db.transactions.getIndexes(); 将给出三个索引。
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "documentation_db.transactions"
},
{
"v" : 1,
"key" : {
"cr_dr" : 1
},
"name" : "cr_dr_1",
"ns" : "documentation_db.transactions"
},
{
"v" : 1,
"key" : {
"cr_dr" : -1
},
"name" : "index on cr_dr desc",
"ns" : "documentation_db.transactions"
}
]
创建索引 { cr_dr : -1 } 时,1 表示索引将按升序排列,-1 表示按降序排列。
版本 ≥ 2.4
散列索引
索引也可以定义为散列索引。这对相等查询更有效,但对范围查询效率不高;不过,你可以在同一字段上定义散列索引和升序/降序索引。
> db.transactions.createIndex({ cr_dr : "hashed" });
> db.transactions.getIndexes(
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "documentation_db.transactions"
},
{
"v" : 1,
"key" : {
"cr_dr" : "hashed"
},
"name" : "cr_dr_hashed",
"ns" : "documentation_db.transactions"
}
]
Section 9.2: 放弃/删除索引
如果索引名称已知
db.collection.dropIndex('name_of_index');
如果不知道索引名称
db.collection.dropIndex( { 'name_of_field' : -1 } );
Section 9.3: 稀疏索引和部分索引
稀疏索引:
稀疏索引对于可选但也应是唯一的字段特别有用。
{ "_id" : "john@example.com", "nickname" : "Johnnie" }
{ "_id" : "jane@example.com" }
{ "_id" : "julia@example.com", "nickname" : "Jules"}
{ "_id" : "jack@example.com" }
由于有两个条目没有指定 “昵称”,而索引会将未指定的字段视为空,因此,如果有两个文档的 “昵称 ”为 “空”,索引创建就会失败:
db.scores.createIndex( { nickname: 1 } , { unique: true, sparse: true } )
会让你的昵称仍然为 “空”。
稀疏索引更紧凑,因为它们会跳过/忽略未指定该字段的文档。因此,如果你有一个只有不到 10%的文档指定了该字段的集合,你就可以创建更小的索引--如果你想进行以下查询,就能更好地利用有限的内存:
db.scores.find({'nickname': 'Johnnie'})
部分索引:
部分索引是稀疏索引所提供功能的超集,应优先于稀疏索引。(3.2 版新增)
部分索引根据指定的过滤器确定索引条目。
db.restaurants.createIndex(
{ cuisine: 1 },
{ partialFilterExpression: { rating: { $gt: 5 } } }
)
如果评分大于 5,那么菜肴将被索引。是的,我们也可以根据其他属性的值指定要索引的属性。
稀疏索引和部分索引的区别:
稀疏索引仅根据索引字段的存在来选择要索引的文档,对于复合索引,则根据索引字段的存在来选择要索引的文档。
部分索引根据指定的过滤器确定索引项。过滤器可以包括索引键以外的字段,也可以指定存在检查以外的条件。
尽管如此,部分索引仍可实现与稀疏索引相同的行为
例如
db.contacts.createIndex(
{ name: 1 },
{ partialFilterExpression: { name: { $exists: true } } }
)
注意:不能同时指定
partialFilterExpression选项和sparse选项。
Section 9.4: 获取集合索引
db.collection.getIndexes();
输出结果
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "documentation_db.transactions"
},
{
"v" : 1,
"key" : {
"cr_dr" : 1
},
"name" : "cr_dr_1",
"ns" : "documentation_db.transactions"
},
{
"v" : 1,
"key" : {
"cr_dr" : -1
},
"name" : "index on cr_dr desc",
"ns" : "documentation_db.transactions"
}
]
Section 9.5: Compound
db.people.createIndex({name: 1, age: -1})
这会在多个字段上创建索引,本例中是在姓名和年龄字段上创建索引。索引将以姓名为升序,年龄为降序。
在这种类型的索引中,排序顺序非常重要,因为它将决定索引是否支持排序操作。复合索引的任何前缀都支持反向排序,只要排序中所有键的排序方向都是反向的。否则,复合索引的排序需要与索引的顺序相匹配。
字段顺序也很重要,在这种情况下,索引将首先按姓名排序,然后在每个姓名值内按年龄字段的值排序。这样就可以通过对姓名字段或姓名和年龄进行查询来使用该索引,但不能仅对年龄进行查询。
Section 9.6: 唯一索引
db.collection.createIndex( { "user_id": 1 }, { unique: true } )
对已定义的索引(单一索引或复合索引)强制执行唯一性。如果集合已包含重复值,建立索引将失败;如果多个条目缺少字段,建立索引也将失败(因为它们都将以空值建立索引),除非指定 sparse: true。
Section 9.7: 单个字段
db.people.createIndex({name: 1})
这会在字段名上创建一个升序单字段索引。
在这类索引中,排序顺序无关紧要,因为 mongo 可以双向遍历索引。
Section 9.8: 删除
要删除索引,可以使用索引名称
db.people.dropIndex("nameIndex")
或索引规范文件
db.people.dropIndex({name: 1})
Section 9.9: List
db.people.getIndexes()
这将返回一个文档数组,每个文档描述了人物集合的一个索引