首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

学习 MongoDB 索引和排序

小小又开始学习了,这次学习的内容是索引和排序。

索引

先给users集合插入两条记录,然后用users集合来进行索引管理的演示:

> user1={"name":"liming","age":20,"gender":"F"}

{ "name" : "liming", "age" : 20, "gender" : "F" }

> db.users.insert(user1)

WriteResult({ "nInserted" : 1 })

> user2={"name":"zhangsan","age":25,"gender":"F"}

{ "name" : "zhangsan", "age" : 25, "gender" : "F" }

> db.users.insert(user1)

WriteResult({ "nInserted" : 1 })

> db.users.count()

2

创建索引:

mongodb使用createIndex()和ensureIndex()方法来创建索引,前者用于3.0及以上版本,后者用于3.0以下版本。语法:

db.COLLECTION_NAME.ensureIndex(keys[,options])

keys:要建立索引的参数列表。如:{KEY:1},其中key表示字段名,1表示升序排序,也可使用使用数字-1降序。options:可选参数,表示建立索引的设置。可选值如下:background,Boolean,在后台建立索引,以便建立索引时不阻止其他数据库活动。默认值为false。unique,Boolean,创建唯一索引。默认值 false。name,String,指定索引的名称。如果未指定,MongoDB会生成一个索引字段的名称和排序顺序串联。partialFilterExpression, document.如果指定,MongoDB只会给满足过滤表达式的记录建立索引.sparse,Boolean,对文档中不存在的字段数据不启用索引。默认值是 false。expireAfterSeconds,integer,指定索引的过期时间storageEngine,document,允许用户配置索引的存储引擎

> db.users.createIndex({"name":1})

{

"createdCollectionAutomatically" : false,

"numIndexesBefore" : 1,

"numIndexesAfter" : 2,

"ok" : 1

}

给name字段创建倒序索引

> db.users.createIndex({"name":-1})

{

"createdCollectionAutomatically" : false,

"numIndexesBefore" : 2,

"numIndexesAfter" : 3,

"ok" : 1

}

给name,age字段创建组合索引

> db.users.createIndex({"name":1,"age":1})

{

"createdCollectionAutomatically" : false,

"numIndexesBefore" : 3,

"numIndexesAfter" : 4,

"ok" : 1

}

在后台给age字段创建索引

> db.users.createIndex({age:1},{background:1})

{

"createdCollectionAutomatically" : false,

"numIndexesBefore" : 4,

"numIndexesAfter" : 5,

"ok" : 1

}

在后台创建索引失败的原因:

在前台创建索引期间会锁定数据库,会导致其它操作无法进行数据读写,在后台创建索引是,会定期释放写锁,从而保证其它操作的运行,但是后台操作会在耗时更长,尤其是在频繁进行写入的服务器上。

查看索引

MongoDB提供的查看索引信息的方法:getIndexes()方法可以用来查看集合的所有索引,getIndexKeys()方法查看索引键。totalIndexSize()查看集合索引的总大小,getIndexSpecs()方法查看集合各索引的详细信息例1:getIndexes()的用法

> db.users.getIndexes()

[

{

"v" : 1,

"key" : {

"_id" : 1

},

"name" : "_id_",

"ns" : "test1.users"

},

{

"v" : 1,

"key" : {

"name" : 1

},

"name" : "name_1",

"ns" : "test1.users"

},

{

"v" : 1,

"key" : {

"name" : -1

},

"name" : "name_-1",

"ns" : "test1.users"

},

{

"v" : 1,

"key" : {

"name" : 1,

"age" : 1

},

"name" : "name_1_age_1",

"ns" : "test1.users"

},

{

"v" : 1,

"key" : {

"age" : 1

},

"name" : "age_1",

"ns" : "test1.users",

"background" : 1

}

]

getIndexKeys()的用法

> db.users.getIndexKeys()

[

{

"_id" : 1

},

{

"name" : 1

},

{

"name" : -1

},

{

"name" : 1,

"age" : 1

},

{

"age" : 1

}

]

totalIndexSize()的用法

> db.users.totalIndexSize()

81920

getIndexSpecs()的用法

> db.users.getIndexSpecs()

[

{

"v" : 1,

"key" : {

"_id" : 1

},

"name" : "_id_",

"ns" : "test1.users"

},

{

"v" : 1,

"key" : {

"name" : 1

},

"name" : "name_1",

"ns" : "test1.users"

},

{

"v" : 1,

"key" : {

"name" : -1

},

"name" : "name_-1",

"ns" : "test1.users"

},

{

"v" : 1,

"key" : {

"name" : 1,

"age" : 1

},

"name" : "name_1_age_1",

"ns" : "test1.users"

},

{

"v" : 1,

"key" : {

"age" : 1

},

"name" : "age_1",

"ns" : "test1.users",

"background" : 1

}

]

删除索引:

不再需要的索引,我们可以将其删除,mongodb提供两种删除索引的方法:dropIndex()方法用于删除指定的索引dropIndexes()方法用于删除全部的索引例1:dropIndex()的用法

> db.users.dropIndex("name_1")

{ "nIndexesWas" : 5, "ok" : 1 }

> db.users.dropIndex("name_1_age_1")

{ "nIndexesWas" : 4, "ok" : 1 }

> db.users.getIndexSpecs()

[

{

"v" : 1,

"key" : {

"_id" : 1

},

"name" : "_id_",

"ns" : "test1.users"

},

{

"v" : 1,

"key" : {

"name" : -1

},

"name" : "name_-1",

"ns" : "test1.users"

},

{

"v" : 1,

"key" : {

"age" : 1

},

"name" : "age_1",

"ns" : "test1.users",

"background" : 1

}

]

我们可以看到,name字段的索引和name与age字段的组合索引皆被删除

dropIndexes()的用法

> db.users.dropIndexes()

{

"nIndexesWas" : 3,

"msg" : "non-_id indexes dropped for collection",

"ok" : 1

}

> db.users.getIndexSpecs()

[

{

"v" : 1,

"key" : {

"_id" : 1

},

"name" : "_id_",

"ns" : "test1.users"

}

]

在使用了dropIndexes()方法后,我们之前建的所有索引都被删除掉了

索引重建:

我们之前把users的索引全部删除了,现在在name字段上建立一个正序索引,然后在name字段上重建倒序索引,可以看到重建索引是把之前name字段的索引删掉再新建一个索引的,重建之前name字段还是只有一个索引.

> db.users.createIndex({name:1})

{

"createdCollectionAutomatically" : false,

"numIndexesBefore" : 1,

"numIndexesAfter" : 2,

"ok" : 1

}

> db.users.getIndexSpecs()

[

{

"v" : 1,

"key" : {

"_id" : 1

},

"name" : "_id_",

"ns" : "test1.users"

},

{

"v" : 1,

"key" : {

"name" : 1

},

"name" : "name_1",

"ns" : "test1.users"

}

]

> db.users.reIndex({name:-1})

{

"nIndexesWas" : 2,

"nIndexes" : 2,

"indexes" : [

{

"key" : {

"_id" : 1

},

"name" : "_id_",

"ns" : "test1.users"

},

{

"key" : {

"name" : 1

},

"name" : "name_1",

"ns" : "test1.users"

}

],

"ok" : 1

}

> db.users.getIndexSpecs()

[

{

"v" : 1,

"key" : {

"_id" : 1

},

"name" : "_id_",

"ns" : "test1.users"

},

{

"v" : 1,

"key" : {

"name" : 1

},

"name" : "name_1",

"ns" : "test1.users"

}

]

索引原理

索引是对数据库表中一列或多列的值进行排序的一种数据结构,可以让我们查询数据库变得更快。为了方便后续介绍,先科普下MongoDB里的索引机制(同样适用于其他的数据库比如mysql)。

> db.person.find()

{ "_id" : ObjectId("571b5da31b0d530a03b3ce82"), "name" : "jack", "age" : 19 }

{ "_id" : ObjectId("571b5dae1b0d530a03b3ce83"), "name" : "rose", "age" : 20 }

{ "_id" : ObjectId("571b5db81b0d530a03b3ce84"), "name" : "jack", "age" : 18 }

{ "_id" : ObjectId("571b5dc21b0d530a03b3ce85"), "name" : "tony", "age" : 21 }

{ "_id" : ObjectId("571b5dc21b0d530a03b3ce86"), "name" : "adam", "age" : 18 }

当你往某各个集合插入多个文档后,每个文档在经过底层的存储引擎持久化后,会有一个位置信息,通过这个位置信息,就能从存储引擎里读出该文档。为方便介绍,统一用pos(position的缩写)来代表位置信息。

比如上面的例子里,person集合里包含插入了5个文档,假设其存储后位置信息如下(为方便描述,文档省去_id字段)

假设现在有个查询 db.person.find( {age: 18} ), 查询所有年龄为18岁的人,这时需要遍历所有的文档(全表扫描),根据位置信息读出文档,对比age字段是否为18。当然如果只有4个文档,全表扫描的开销并不大,但如果集合文档数量到百万、甚至千万上亿的时候,对集合进行全表扫描开销是非常大的,一个查询耗费数十秒甚至几分钟都有可能。

如果想加速 db.person.find( {age: 18} ),就可以考虑对person表的age字段建立索引。

db.person.createIndex( {age: 1} ) // 按age字段创建升序索引

建立索引后,MongoDB会额外存储一份按age字段升序排序的索引数据,索引结构类似如下,索引通常采用类似btree的结构持久化存储,以保证从索引里快速(O(logN)的时间复杂度)找出某个age值对应的位置信息,然后根据位置信息就能读取出对应的文档。

简单的说,索引就是将文档按照某个(或某些)字段顺序组织起来,以便能根据该字段高效的查询。

众所周知,MongoDB默认会为插入的文档生成_id字段(如果应用本身没有指定该字段),_id是文档唯一的标识,为了保证能根据文档id快递查询文档,MongoDB默认会为集合创建_id字段的索引。

> db.person.getIndexes() // 查询集合的索引信息

[

{

"ns" : "test.person", // 集合名

"v" : 1, // 索引版本

"key" : { // 索引的字段及排序方向

"_id" : 1 // 根据_id字段升序索引

},

"name" : "_id_" // 索引的名称

}

]

排序

MongoDB sort() 方法

在 MongoDB 中使用 sort() 方法对数据进行排序,sort() 方法可以通过参数指定排序的字段,并使用 1 和 -1 来指定排序的方式,其中 1 为升序排列,而 -1 是用于降序排列。

例子

col 集合中的数据如下:

{ "_id" : ObjectId("56066542ade2f21f36b0313a"), "title" : "PHP 教程", "description" : "PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "php" ], "likes" : 200 }

{ "_id" : ObjectId("56066549ade2f21f36b0313b"), "title" : "Java 教程", "description" : "Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言。", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "java" ], "likes" : 150 }

{ "_id" : ObjectId("5606654fade2f21f36b0313c"), "title" : "MongoDB 教程", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb" ], "likes" : 100 }

以下实例演示了 col 集合中的数据按字段 likes 的降序排列:

>db.col.find({},{"title":1,_id:0}).sort({"likes":-1})

{ "title" : "PHP 教程" }

{ "title" : "Java 教程" }

{ "title" : "MongoDB 教程" }

>

小注意

skip(), limilt(), sort()三个放在一起执行的时候,执行的顺序是先 sort(), 然后是 skip(),最后是显示的 limit()。

小明菜市场

推荐阅读

●学习 | Docker 从入门到精通 第二季

●学习 | Docker 从入门到精通

●学习 | Spring Cloud Config 从入门到精通

●明知 | js中类定义和类继承

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20200730A00ULG00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券