感谢 Karl Seguin 编写的 The Little MongoDB Book 这本 MongoDB 入门书。javascript
本文内容主要来自「The Little MongoDB Book」的学习,学习笔记基于我的理解对原书部份内容进行调整。html
若是你是 MongoDB 数据库初学者,建议从学习「The Little MongoDB Book」 开始。java
若是须要练习 MongoDB 相关命令行工具可直接阅读本学习笔记。git
笔者测试 MongoDB 数据库版本较早,但文中涉及的全部 MongoDB 概念及命令行工具基本适用于全部版本。github
了解 MongoDB 前先了解 NoSQL,NoSQL 是一种数据存储系统(非关系型数据库系统),相比 MySQL 这类关系型数据库提供通用的数据存储解决方案,NoSQL 倾向负责解决系统中一部分数据存储问题。算法
MongoDB 是一种 NoSQL 解决方案,提供更加通用的 NoSQL 方案。mongodb
本文约定 Mongo 和 MongoDB 都是代指 MongoDB 数据库系统。shell
在学习 MongoDB 以前,须要安装 MongoDB 环境。可到 官方下载页面 下载须要的 MongoDB 版本。数据库
dbpath=PATH_TO_WHERE_YOU_WANT_TO_STORE_YOUR_DATABASE_FILES
例如,在 Windows 中您须要添加的多是 dbpath=c:\mongodb\data,而在Linux下可能就是 dbpath=/etc/mongodb/data。数组
上面的安装步骤用于安装和启动 MongoDB 服务器进程。下面以 Windows 系统为例,讲解 MongoDB 安装及启动详细过程。
对于不建立 c:\mongodb\bin\mongodb.config配置的用户,能够经过 --dbpath 参数启动服务,执行 c:\mongodb\bin\mongod --dbpath c:\mongodb\data\;效果和使用 --config 参数同样。
接下来,咱们经过 SHELL 环境链接 MongoDB 服务。进入 c:\mongodb\bin 目录,执行 mongo 命令,便可完成 MongoDB 服务链接。
须要说明的是 MongoDB 在 c:\mongodb\bin,提供了一些工具,其中就包括上去的 mongod.exe 和 mongo.exe,它们对应 mongod 和 mongo 命令。
若是有使用过关系型数据库(如 MySQL),那么对数据库、表、行、字段这些概念不会陌生,在 MongoDB 中也有相似的数据结构,不过在 Mongo 中将以另外一种形式存在:
MongoDB 和 关系型数据库相关概念关系对照表:
SQL术语/概念 | MongoDB术语/概念 | 解释/说明 |
---|---|---|
database | database | 数据库 |
table | collection | 数据库表/集合 |
row | document | 数据记录行/文档 |
column | field | 数据字段/域 |
index | index | 索引 |
table joins | 表链接,MongoDB不支持 | |
primary key | primary key | 主键,MongoDB自动将_id字段设置为主键 |
表格信息引用自 MongoDB 概念解析
下文中全部命令,需在命令终端执行。当使用 mongo 命令成功链接 MongoDB 服务后,可使用 help 获取 MongoDB 数据库使用帮助,它的执行结果大体以下:
> help db.help() help on db methods db.mycoll.help() help on collection methods rs.help() help on replica set methods help admin administrative help help connect connecting to a db help help keys key shortcuts help misc misc things to know help mr mapreduce show dbs show database names show collections show collections in current database show users show users in current database show profile show most recent system.profile entries with time >= 1ms show logs show the accessible logger names show log [name] prints out the last segment of log in memory, 'global' is default use <db_name> set current database db.foo.find() list objects in collection foo db.foo.find( { a : 1 } ) list objects in foo where a == 1 it result of the last line evaluated; use to further iterate DBQuery.shellBatchSize = x set default number of items to display on shell exit quit the mongo shell
1 显示 MongoDB 数据库
执行 show dbs,显示 MongoDB 全部数据库
2 切换 MongoDB 数据库
执行 use test,将工做数据库切入到 test 数据库。在 MongoDB 中没有相似关系数据库的 Schema 概念,因此即便 MongoDB 的数据库未建立,也能够任意切换工做数据库。
3 显示数据库中的集合(collection)
执行 show colections,会打印输出当前数据库中的全部数据库集合。
4 获取工做数据库帮助信息
当使用 use test 进入 test 数据库后,能够执行 db.help() 指令查看 database 级别支持的命令,结果以下:
> db.help() DB methods: db.addUser(username, password[, readOnly=false]) db.auth(username, password) db.cloneDatabase(fromhost) db.commandHelp(name) returns the help for the command db.copyDatabase(fromdb, todb, fromhost) db.createCollection(name, { size : ..., capped : ..., max : ... } ) db.currentOp() displays the current operation in the db db.dropDatabase() db.eval(func, args) run code server-side db.getCollection(cname) same as db['cname'] or db.cname db.getCollectionNames() db.getLastError() - just returns the err msg string db.getLastErrorObj() - return full status object db.getMongo() get the server connection object db.getMongo().setSlaveOk() allow this connection to read from the nonmaster member of a replica pair db.getName() db.getPrevError() db.getProfilingLevel() - deprecated db.getProfilingStatus() - returns if profiling is on and slow threshold db.getReplicationInfo() db.getSiblingDB(name) get the db at the same server as this one db.isMaster() check replica primary status db.killOp(opid) kills the current operation in the db db.listCommands() lists all the db commands db.logout() db.printCollectionStats() db.printReplicationInfo() db.printSlaveReplicationInfo() db.printShardingStatus() db.removeUser(username) db.repairDatabase() db.resetError() db.runCommand(cmdObj) run a database command. if cmdObj is a string, turns it into { cmdObj : 1 } db.serverStatus() db.setProfilingLevel(level,<slowms>) 0=off 1=slow 2=all db.shutdownServer() db.stats() db.version() current version of the server db.getMongo().setSlaveOk() allow queries on a replication slave server db.fsyncLock() flush data to disk and lock server for backups db.fsyncUnock() unlocks server following a db.fsyncLock()
5 查看工做数据库名
须要查看当前工做的数据库,执行以下命令
> db.getName() test1
6 查看工做数据库统计信息
db.stats() 会列出工做数据库中 集合、数据库大小等有用的信息。
> db.stats() { "db":"test", --查看的是哪一个数据库 "collections":7, --collection数量 "objects":28, --对象数量 "avgObjSize":50.57142857142857, --对象平均大小 "dataSize":1416, --数据大小 "storageSize":31744, --数据大小(含预分配空间) "numExtents":7, --事件数量 "indexes":7, --索引数量 "indexSize":57344, --索引大小 "fileSize":50331648, --文件大小 "ok":1 --本次取stats是否正常 }
上例结果引用自 db.stats() - 显示当前db状态
7 删除数据库
当须要删除 某个 数据库时,请先使用 use 指令切换工做数据库至待删除数据库。而后执行 db.dropDatabase() 指令。
> show dbs local (empty) test 0.03125GB test1 (empty) > use test1 switched to db test1 > db.dropDatabase() { "dropped" : "test1", "ok" : 1 } > show dbs local (empty) test 0.03125GB
有了上面的基本概念,咱们就知道如何使用 MongoDB 的数据库和数据集了,下面是一个小练习,来加深相关知识的使用及理解:
场景:咱们开辟一个训练场,将完成数据库服务启动、客户端链接 MongoDB 服务、查看和选择数据库及数据库删除操做。
约定在 shell 中以 -- 开始的注释说明信息:执行时请不要赋值注释信息。
-- 1. 启动一个 Windows 命令行窗口,开启 MongoDB 服务 > cd c:\mongodb\bin > mongod --config c:\mongodb\bin\mongodb.config -- 2. 另启动一个 Windows 命令行窗口链接 MongoDB 服务 > cd c:\mongodb\bin > mongo MongoDB shell version: 2.0.7 connecting to: test -- 3. 查看全部数据库 > show dbs local (empty) test 0.03125GB test1 (empty) -- 4. 切换工做数据库至 blog > use blog switched to db blog -- 5. 查看当前工做数据库 > db.getName() blog -- 6. 切换工做数据库至 test > use test switched to db test -- 7. 查看当前工做数据库 > db.getName() test -- 8. 切回工做数据库至 blog > use blog switched to db blog -- 9. 查看 blog 库的全部集合, 因为是空数据库因此会没有返回信息 > show collections -- 10 查看 blog 库的状态,因为是空数据库因此统计信息内相关数据为空 > db.stats() { "db" : "blog", "collections" : 0, "objects" : 0, "avgObjSize" : 0, "dataSize" : 0, "storageSize" : 0, "numExtents" : 0, "indexes" : 0, "indexSize" : 0, "fileSize" : 0, "nsSizeMB" : 0, "ok" : 1 } -- 11. 插入一个用户到 blog 数据库的 user 集合里。 -- 不知道如何插入?不要紧,直接复制下面的命令就行了。 > db.user.insert({name: 'huliuqing', age: 18, hobby: ['coding', 'reading']}) -- 12. 查看刚刚 user 集合的插入结果 > db.user.find() { "_id" : ObjectId("5abde35e7d318c10d73539e3"), "name" : "huliuqing", "age" : 18, "hobby" : [ "coding", "reading" ] } -- 13. 再看下 blog 库的状态 > db.stats() { "db" : "blog", "collections" : 3, "objects" : 5, "avgObjSize" : 51.2, "dataSize" : 256, "storageSize" : 16384, "numExtents" : 3, "indexes" : 1, "indexSize" : 8176, "fileSize" : 16777216, "nsSizeMB" : 16, "ok" : 1 } -- 14. 删除 user 集合 -- 不知道使用什么命令?那先来查看下 user 集合层级的帮助信息吧 > db.user.help() ... db.user.drop() drop the collection ... > db.user.drop() true -- 14. 再看下 blog 库的状态 { "db" : "blog", "collections" : 2, "objects" : 1, "avgObjSize" : 36, "dataSize" : 36, "storageSize" : 8192, "numExtents" : 2, "indexes" : 0, "indexSize" : 0, "fileSize" : 16777216, "nsSizeMB" : 16, "ok" : 1 } -- 15. 删除 blog 数据库 > db.dropDatabases() { "dropped" : "blog", "ok" : 1 } -- 16. 再看下 blog 库的状态 > db.stats() { "db" : "blog", "collections" : 0, "objects" : 0, "avgObjSize" : 0, "dataSize" : 0, "storageSize" : 0, "numExtents" : 0, "indexes" : 0, "indexSize" : 0, "fileSize" : 0, "nsSizeMB" : 0, "ok" : 1 } -- 17 查看下数据库 > show dbs local (empty) test 0.03125GB test1 (empty)
另外须要说明的是 MongoDB 的 SHELL 运行于 JavaScript 之上。除全局命令外,操做 db 数据库、 db.COLLECTION_NAME 操做集合,若缺乏 () 将会在 SHELL 里打印出方法的实现源码。
前面咱们学习了如何使用 MongoDB 的帮助,接下来在学习 CRUD 操做以前,进一步了解下 MongoDB 的数据库及集合是如何建立的。
MongoDB 是 无模式 的,当使用 use YOUR_DATABASE 命令切换数据库时,咱们无需预先建立 YOUR_DATABASE 数据库,而当向某个 集合 插入一个 文档 时,将会自动生成具体的数据库、集合和文档。
如:
> use mongo_playground > db.users.insert({name: 'huliuqing', age: 18, gender: 'male'})
上面的命令对 users 集合作 insert(插入文档) 操做,传入的参数是一个 JSON 格式数据。经过 show collections 命令查看到有: users 和 system.indexes 两个集合存在,其中 system.indexes 集合会在每一个 数据库 由 MongoDB 自主建立,这个集合包含数据库中的索引信息。
在执行 insert 命令时,MongoDB 会生成一个值为 ObjectId 类型的 _id 域。_id 域 对每一个 文档 都是必须的,它相似于 SQL 的主键,咱们可使用本身的算法生成 _id 的值,大部分状况下使用 MongoDB 的默认值就能够了。
前面说过 _id 域 相似主键,它的索引信息被存储在 system.indexes 集合内,咱们看看两个集合里有什么数据:
-- 1. 查看集合 > show collections system.indexes users -- 2. 查看 users 集合数据 > db.users.find().pretty() { "_id" : ObjectId("5ac2f7ecfdcd54e4d368bde5"), "name" : "huliuqing", "age" : 18, "gender" : "male" } -- 3. 查看 system.indexes 集合数据 > db.system.indexes.find().pretty() { "v" : 1, "key" : { "_id" : 1 }, "ns" : "mongo_playground.users", "name" : "_id_" }
从结果咱们能够看到 users 集合比添加的 JSON 多了 _id 域,它的索引信息被 system.indexes 集合记录。
建立一个 文档 由 db.YOUR_COLLECTION.insert() 命令完成,咱们向 db.users 集合插入一条新的文档:
-- 1. 建立文档 > db.users.insert({name: 'zhangsanfeng', age: 120, gender: 'male', hobby: ['Kung fu', 'Tai Chi']}); -- 2. 查询结果 > db.users.find() { "_id" : ObjectId("5ac2f7ecfdcd54e4d368bde5"), "name" : "huliuqing", "age" : 18, "gender" : "male" } { "_id" : ObjectId("5ac3165bfdcd54e4d368bde6"), "name" : "zhangsanfeng", "age" : 120, "gender" : "male", "hobby" : [ "Kung fu", "Tai Chi" ] }
一个简单的查询操做可使用 db.YOUR_COLLECTION.find() 指令来获取全部 YOUR_COLLECTION 集合的全部文档列表。除此以外,咱们还须要知道在 MongoDB 中有个 查询构造器 的概念,查询构造器 相似于 SQL 中的 WHERE 语句
在学习查询构造器以前,咱们先清洗下 mongo_playground 数据库,并加入测试集合。
-- 1. 进入 mongo_playground 数据库 > use mongo_playground -- 2. 删除 mongo_playground 数据库 > db.dropDatabase() -- 3. 建立测试数据 db.users.insert({name: 'Bob',birthday: new Date(1992,2,13,7,47),hobby: ['basketball','football'],weight: 60,gender: 'm',age: 18}); db.users.insert({name: 'John',birthday: new Date(1991, 0, 24, 13, 0),hobby: ['basketball', 'ping pong'],weight: 45,gender: 'm',age: 23}); db.users.insert({name: 'Tony',birthday: new Date(1973, 1, 9, 22, 10),hobby: ['boxing', 'racing'],weight: 98,gender: 'm',age: 30}); db.users.insert({name: 'Lily',birthday: new Date(1997, 6, 1, 10, 42),hobby: ['ping pong', 'yoga'],weight: 69,gender: 'f',age: 39}); db.users.insert({name: 'Jack',birthday: new Date(1979, 7, 18, 18, 44),hobby: ['skiing'],weight: 57,gender: 'm',age: 51}); db.users.insert({name: 'Tom',birthday: new Date(1985, 6, 4, 2, 1),hobby:['skiing', 'basketball','boxing'],weight:65,gender:'m',age:29}); db.users.insert({name: 'Jackson',birthday: new Date(1998, 2, 7, 8, 30),hobby: ['skateboard', 'running'],weight: 73,gender: 'f',age: 41}); db.users.insert({name: 'Lucy',birthday: new Date(2005, 4, 3, 0, 57),hobby: ['skiing', 'yoga'],weight: 42,gender: 'f',age: 22}); db.users.insert({name: 'Peter',birthday: new Date(2001, 9, 8, 14, 53),hobby: ['shooting', 'darts'],weight: 60,gender: 'm',age: 48}); db.users.insert({name: 'Rose',birthday: new Date(1997, 2, 1, 5, 3),hobby: ['shooting', 'darts'],weight: 65,gender: 'f',age: 56}); db.users.insert({name: 'Lee',birthday: new Date(1999, 11, 20, 16, 15),hobby: ['ping pong', 'basketball'],weight: 54,gender: 'm'});
查找用户 name 等于 Lee 的信息
> db.users.find({name: 'Lee'}).pretty() { "_id" : ObjectId("5ac31e00fdcd54e4d368bdfc"), "name" : "Lee", "birthday" : ISODate("1999-12-20T08:15:00Z"), "hobby" : [ "ping pong", "basketball" ], "weight" : 54, "gender" : "m" }
查找喜欢 跑步 的 男性
> db.users.find({gender: 'm', hobby: 'racing'}).pretty() { "_id" : ObjectId("5ac31e00fdcd54e4d368bdf4"), "name" : "Tony", "birthday" : ISODate("1973-02-09T14:10:00Z"), "hobby" : [ "boxing", "racing" ], "weight" : 98, "gender" : "m", "age" : 30 }
查找喜欢 乒乓球 或 瑜伽 的 男性
-- 1. 仅查找喜欢 乒乓球 或 瑜伽 的用户 > db.users.find({gender: 'm', $or: [{hobby: 'ping pong'}, {hobby: 'yoga'}]}) { "_id" : ObjectId("5ac327edfdcd54e4d368be09"), "name" : "John", "birthday" : ISODate("1991-01-24T05:00:00Z"), "hobby" : [ "basketball", "ping pong" ], "weight" : 45, "gender" : "m", "age" : 23 } { "_id" : ObjectId("5ac327edfdcd54e4d368be12"), "name" : "Lee", "birthday" : ISODate("1999-12-20T08:15:00Z"), "hobby" : [ "ping pong", "basketball" ], "weight" : 54, "gender" : "m" } -- 2. 下面的查找将查找到全部的喜欢 乒乓球 或 瑜伽 的用户 > db.users.find({$or: [{hobby: 'ping pong'}, {hobby: 'yoga'}]})
经过 $lt(less than: 小于)**、**$lte(less than and equal: 小于等于)、$gt(greater than: 大于)**、**$gte(greater than and equal: 大于等于) 和 $ne(not equal: 不等于) 等实现比较查询。
-- 1. 查询年龄大于等于 30 岁且小于 40 岁的用户 > db.users.find({age: {$gte: 30, $lt: 40}}) -- 2. 查询年龄大于 55 岁的用户 > db.users.find({age: {$gt: 55}}) -- 3. 查询年龄小于 18 岁的用户 > db.users.find({age: {$lt: 20}}) -- 4. 查询年龄不等于 18 岁的用户 > db.users.find({age: {$ne: 18}})
在 3.2.1.4 的第 4 个示例 4. 查询年龄不等于 18 岁的用户 会查询到没有 age 域的用户 Lee。经过 $exists 指令能够判断某个域是否存在,它的值是 bool 类型,咱们对这个示例作些改进:
-- 1. 查询年龄字段存在且年龄不等于 18 岁的用户 > db.users.find({age: {$ne: 18, $exists: true}})
本章了解了 MongoDB 相关查询操做,了解更多查询命令细节能够查看 查询文档。但更重要的是反复练习这些查询语句的基本用法。
MongoDB 的更新须要特别关注一下,更新数据使用 db.YOUR_COLLECTIONS.update(query, object, options) 方法,update 接收两个必选参数:查询选择器 和 须要更新的域。
一个简单的示例,咱们找到 年龄 48 岁 的用户 Peter,将他的年龄 更新为 49 岁。
> db.users.find({age: 48}).pretty() { "_id" : ObjectId("5ac42ff514c16270040db426"), "name" : "Peter", "birthday" : ISODate("2001-10-08T06:53:00Z"), "hobby" : [ "shooting", "darts" ], "weight" : 60, "gender" : "m", "age" : 48 } > db.users.update({age: 48}, {age: 49}) > db.users.find({age: 49}).pretty() { "_id" : ObjectId("5ac42ff514c16270040db426"), "age" : 49 }
再次查找 年龄 49 岁 的用户,会发现 更新后 Perter 用户数据被 覆盖 为 { "_id" : ObjectId("5ac42ff514c16270040db426"), "age" : 49 }(由于 ObjectId 相同)。
这是由于: 在 MongoDB 中接收的第二个参数,若是没有使用 $set 修饰符,将会采起 覆盖 文档操做,而不是 更新文档指定域,这和 SQL 的 UPDATE 语句行为不同。
正确的更新 应该是下面的 update 写法使用 {$set: {age: 49}},操做以前咱们要清空并重建测试数据。
> db.users.find({age: 48}).pretty() { "_id" : ObjectId("5ac42ff514c16270040db426"), "name" : "Peter", "birthday" : ISODate("2001-10-08T06:53:00Z"), "hobby" : [ "shooting", "darts" ], "weight" : 60, "gender" : "m", "age" : 48 } > db.users.update({age: 48}, {$set: {age: 49}}) > db.users.find({age: 49}).pretty() { "_id" : ObjectId("5ac4375b14c16270040db43c"), "name" : "Peter", "birthday" : ISODate("2001-10-08T06:53:00Z"), "hobby" : [ "shooting", "darts" ], "weight" : 60, "gender" : "m", "age" : 49 }
建议: 在执行 删除、更新 这类操做前,建议先采用相同的查询条件查找数据,结果与判断一致时再作 删除、更新 等操做。
-- 1. Peter 又长大了一岁 > db.users.find({name: 'Peter'}) { "_id" : ObjectId("5ac4375b14c16270040db43c"), "name" : "Peter", "birthday" : ISODate("2001-10-08T06:53:00Z"), "hobby" : [ "shooting", "darts" ], "weight" : 60, "gender" : "m", "age" : 49 } > db.users.update({name: 'Peter'}, {$inc: {age: 1}}) -- 2. Peter 越活越年轻 > db.users.find({name: 'Peter'}) { "_id" : ObjectId("5ac4375b14c16270040db43c"), "name" : "Peter", "birthday" : ISODate("2001-10-08T06:53:00Z"), "hobby" : [ "shooting", "darts" ], "weight" : 60, "gender" : "m", "age" : 50 } > db.users.update({name: 'Peter'}, {$inc: {age: -5}}) -- 3. 由于 Peter 有了更多的兴趣爱好 > db.users.update({name: 'Peter'}, {$push: {hobby: 'racing'}}) { "_id" : ObjectId("5ac4375b14c16270040db43c"), "age" : 45, "birthday" : ISODate("2001-10-08T06:53:00Z"), "gender" : "m", "hobby" : [ "shooting", "darts", "racing" ], "name" : "Peter", "weight" : 60 }
MongoDB update 方法第三个参数接收 bool 值的标识符,该值默认为 false。当该值设为 true 时若 查询选择器 的目标文档存在,则采起 update $set 域 操做;若不存在则采起 INSERT 操做。
这个选项在相似 网站点击计数器 统计场景中很是有用。若是网页点击记录存在则更新记录数,不存在则执行插入操做。
-- 1. 给 users 页面统计点击数, update 第三个参数为 false 或 缺省,将不会建立 hits 集合 > db.hits.update({page: 'users'}, {$inc: {hits: 1}}) > db.hits.find() -- 2. upsert 选项设置为 true,在执行 update 更新操做时,hits 集合未建立,执行建立操做 > db.hits.update({page: 'users'}, {$inc: {hits: 1}}, {upsert: true}) > db.hits.find() { "_id" : ObjectId("5ac4427bb5b4350bc6d2f715"), "hits" : 1, "page" : "users" } -- 3. upsert 选项设置为 true,在执行 update 更新操做时,hits 集合已建立,执行更新操做 > db.hits.update({page: 'users'}, {$inc: {hits: 1}}, {upsert: true}) > db.hits.find() { "_id" : ObjectId("5ac4427bb5b4350bc6d2f715"), "hits" : 2, "page" : "users" }
MongoDB update 操做在 3.3.1 介绍过,更新数据须要 $set 修饰符,不然执行覆盖操做。这里咱们介绍它的第二个独特特性:默认更新一条记录。
当咱们须要给全部用户加上点赞数 likes 域用于记录用户获得的赞,咱们会想下面的方法同样执行,但仅仅只有一条文档加上了 likes 域:
> db.users.update({}, {$set:{likes: 0}}) > db.users.find({likes: 0})
multi 选项值设为 true 能够实现全部文档记录新增 域 操做。
> db.users.update({}, {$set:{likes: 0}}, false, true) > db.users.find({likes: 0})
能够在文档查看 update 方法相关具体使用。
经过 db.YOUR_COLLECTION.remove(query, justOne) 能够删除一个或全部 文档,参数接收的查询选择器为空时删除全部文档,当 justOne 标识为 true 是仅删除一条匹配文档。
-- 1. 删除用户 Bob 的记录 > db.users.find({name: 'Bob'}) > db.users.remove({name: 'Bob'}) > db.users.find({name: 'Bob'}) -- 2. 删除全部用户 > db.users.find() > db.users.remove() > db.users.find()
相关细节能够查阅 删除文档。
若是须要删除全部文档,咱们还能够经过 db.YOUR_COLLECTIONS.drop() 方法实现,drop() 方法不只删除全部文档还会删除该集合的索引信息。
咱们在 3.2 章节中了解了有关 MongoDB 的查询功能。本节咱们将学习包括查询指定域、排序、返回的结果集记录数限制和分页等功能,这些方法在应用程序开发过程当中会十分常见。
在 Mongo Shell 里咱们经过 db.YOUR_COLLECTION.find 注意 无 () 能够看到 find 方法的具体实现,find 一共能够接收 4 个参数:第一个参数是查询选择器;第二个参数即为指定返回的域。
以前,咱们都是返会全部的域信息,如今让咱们仅返回用户的用户名、年龄和性别:
> db.users.find({}, {name: true, age: true, gender: true}) { "_id" : ObjectId("5acada245c193d1acc967575"), "name" : "Bob", "gender" : "m", "age" : 18 } { "_id" : ObjectId("5acada245c193d1acc967576"), "name" : "John", "gender" : "m", "age" : 23 } { "_id" : ObjectId("5acada245c193d1acc967577"), "name" : "Tony", "gender" : "m", "age" : 30 } ...
默认 _id 域总会做为查询结果返回,能够设置 {_id: falsee} 显示的排除掉。
在 MongoDB 中咱们还须要了解一个基本概念 游标(cursor),因为前面咱们并无涉及到游标的使用(只是看起来没有涉及到游标)。
find 方法返回的结果即为依据查询选择器匹配到的文档集合的 游标,这样能够经过链式操做对 find 结果集进行处理。
咱们在 MongoDB Shell 里输入 db.users.help() 命令能够看到下面的帮助信息:
> db.users.help() ... db.users.find([query],[fields]) - query is an optional query filter. fields is optional set of fields to return. e.g. db.users.find( {x:77} , {name:1, x:1} ) db.users.find(...).count() db.users.find(...).limit(n) db.users.find(...).skip(n) db.users.find(...).sort(...) ...
count、limit、skip、sort 等方法便是做用在 find 返回的游标上。
下面咱们依据用户的年龄按照 升序 或 降序 排列:
-- 1. 依据升序排列 > db.users.find({}, {name: 1, age: 1}).sort({age: 1}) -- 2. 依据降序排列 > db.users.find({}, {name: 1, age: 1}).sort({age: -1})
要实现分页功能须要结合使用 skip(n) 和 limit(n) 两个方法,它们的返回值也是一个游标。skip 会选择游标的起始位置,limit 相似 SQL 的 limit 语句表示返回的结果集最大纪录条数。
下面咱们查下年龄第二和第三大的用户:
-- 1. 先看下年龄最大的 5 名用户 > db.users.find({}, {name: true, age: 1}).sort({age: -1}).limit(5) -- 2. 再看下年龄第二和第三大的用户 > db.users.find({}, {name: true, age: 1}).sort({age: -1}).skip(1).limit(2)
在 MongoDB 中能够直接使用 db.YOUR_COLLECTION.count() 方法获取集合记录数,也能够经过 db.YOUR_COLLECTION.find().count() 获取:
获取年龄大于等于 20 岁的用户数:
> db.users.count({age: {$gte: 20}}) > db.users.find({age: {$gte: 20}}).count()
可是要知道 db.YOUR_COLLECTION.count() 仅仅是 db.YOUR_COLLECTION.find().count() 的别名,在它的内部仍是调用 db.YOUR_COLLECTION.find().count()
> db.users.count function (x) { return this.find(x).count(); }
更多有关做用于游标的方法能够查阅 游标方法
TO BE CONTINUE