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

索引

先给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字段)

位置信息 文档
pos1 {“name” : “jack”, “age” : 19 }
pos2 {“name” : “rose”, “age” : 20 }
pos3 {“name” : “jack”, “age” : 18 }
pos4 {“name” : “tony”, “age” : 21}
pos5 {“name” : “adam”, “age” : 18}

假设现在有个查询 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值对应的位置信息,然后根据位置信息就能读取出对应的文档。

AGE 位置信息
18 pos3
18 pos5
19 pos1
20 pos2
21 pos4

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

众所周知,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()。

学习 | MongoDB 索引和排序相关推荐

  1. MongoDB学习系列 -- 索引

    百度百科上对于索引的定义大概是这样的:在关系数据库中,索引是一种单独的.物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的 ...

  2. mongodb学习(六)索引

    准备工作: 先插入100万条数据 for(i=0;i<=1000000;i++){db.users.insert({"i":i,"username":&q ...

  3. Mongodb 索引 对查询结果的排序

    本文主要讨论 "mongodb的索引" 和 "查询结果的排序" 之间的关系,索引对排序有什么影响,为什么有影响,应该遵循什么规则. 1. 先从创建单字段索引,认 ...

  4. mongodb索引生成HTML页面,mongodb高阶:索引创建、聚合查询、复制集、分片、创建备份和部署...

    先前我们讨论了mongodb的进阶查询:投影查询.分页查询以及对查询结果进行排序,从本节起我们开始学习mongodb相关的高级技术,首先我们会讨论mongodb如何创建索引,索引是数据库中最重要的东西 ...

  5. MongoDB索引原理及实践

    背景 数据库的演进 随着计算机的发展,越来越多的数据需要被处理,数据库是为处理数据而产生.从概念上来说,数据库是指以一定的方式存储到一起,能为多个用户共享,具有更可能小的冗余,与应用程序彼此独立的数据 ...

  6. 后端开发-MySQL学习之索引机制最详细版(B+树)

    一.索引是什么? 索引是为了加速对表中数据行的检索而创建的一种分散存储的数据结构.而且是实现了高级查找算法的数据结构,索引一般以文件形式存储在磁盘上,索引检索需要磁盘I/O操作. 文章视频讲解:后端开 ...

  7. mongodb 子文档排序_猫鼬101:基础知识,子文档和人口简介

    mongodb 子文档排序 Mongoose is a library that makes MongoDB easier to use. It does two things: Mongoose是一 ...

  8. MongoDB 索引

    2019独角兽企业重金招聘Python工程师标准>>> 索引Indexes 索引常常用来大幅度的提升查询的性能. 考虑应用程序的查询种类是非常重要的事情,因此你就要定义相关的索引. ...

  9. MongoDB · 引擎特性 · MongoDB索引原理

    MongoDB · 引擎特性 · MongoDB索引原理 数据库内核月报 原文链接 http://mysql.taobao.org/monthly/2018/09/06/ 为什么需要索引? 当你抱怨M ...

最新文章

  1. PyTorch常用代码段整理合集,建议收藏!
  2. php error log 函数,php日志函数error_log如何使用 php日志函数error_log用法介绍
  3. JavaScript原型链的理解
  4. yolov配置之:cuda、 cudnn安装
  5. mysql不复制数据_windows mysql不停止服务复制数据
  6. python程序设计方法_Python程序设计现代方法
  7. 创建 demo.html,demo.html
  8. DataGridView使用技巧二:设置单元格只读
  9. 不×××,用google!!
  10. EvilAP_Defender:可以警示和攻击 WIFI 热点陷阱的工具
  11. Firefox浏览器个人用的插件
  12. 2022-渗透测试-口令破解-几款暴力破解和字典生成的工具
  13. 防控青光眼的3大武器
  14. 精灵图使用——如何利用js循环实现精灵图设置
  15. 爱测未来安全-浅淡流量劫持及应对措施
  16. 但是我喜欢计算机课用英语怎么说,语文课的英文
  17. 复杂网络2012年度盘点:博弈+传播+控制
  18. python 菜品识别_菜品识别-python
  19. linux time 查看cp,Linux命令:cp、time、cut、awk 、獲取文件大小命令
  20. 看了多篇2019年的面经后的个人总结

热门文章

  1. 使用 Typescript 踩 react-redux 的坑
  2. 《OpenGL编程指南(原书第9版)》——3.2 OpenGL缓存数据
  3. 创建动态链接库时设置导出函数的方法
  4. OrCAD Capture使用记录
  5. 《C++Primer》复习——with C++11 [1]
  6. 条款05:了解C++默默编写并调用哪些函数
  7. 【git系列】git命令之撤销回退篇
  8. js视频html代码,html+JS刷图实现视频效果(示例代码)
  9. [LeetCode] Majority Element II
  10. 关于操作 ASP.NET Web API的实例