1. 什么是MongoDB?
MongoDB是一个开源NoSQL(NotOnly SQL)分布式数据库,不同于MySQL的关系型数据库。它所有的数据以文档(Binary JSON文档)的形式存储。没有表和行的概念。
1. 基本概念
数据库(database):一个Mongo实例对应多个数据库。
Mongo中的数据库等同于MySql中的数据库。
集合(collection): 数据库由集合组成。
Mongo中的集合等同于MySql中的表(table)。
文档(document):集合由文档组成。
Mongo中的文档等同于MySql中的记录(row)。
key: 文档由key-value组成。
Mongo中的key相当于MySql中的列(field)。
2. 优缺点
优点:
1) 高并发
2)大数据量
3)分布式(多台服务器)
缺点:
不可靠,会出现数据丢失
3. ObjectId
在MySql数据库中,id是自增ID。在MongoDB这种分布式数据库中,该方法不实用; 在该数据库中,使用12个字节字符串组成的ObjectId类型。
- 4字节: UNIX时间戳
- 3字节:运行MongoDB数据库的机器的MAC地址
- 2字节:生成该Id的进程
- 3字节:随机数
2. MongoDB的安装
1. windows系统
下载安装包,解压,打开bin目录
cd MongoDB/bin
启动服务器端(默认断开27017)
// data是数据存放目录 mongod --dbpath=./data
mongod命令的其他参数:
--port 指定端口号;默认端口是27017 --logpath 指定日志文件;不是文件目录 --logappend 使用追加的方式追加日志 --dbpath 指定数据库路径 --directoryperdb 设置每个数据库在单独的目录
监听客户端请求
mongo // 成功的标志是出现>
2. MacOS系统
brew tap mongodb/brew
// $ brew install <formula> eg: brew install mongodb-community
监听客户端请求
mongo
安装后的文件夹所在的目录
/usr/local/Cellar/mongodb-community/
3. MongoDB的命令
查看mongoDB的所有命令:
db.help();
1. 操作数据库
1. 创建数据库
使用use,切换到对应的数据库。如果数据库不存在,则创建数据库
use dbname;
2. 查看数据库列表
show dbs;
3. 删除数据库
先切换到数据库;再删除
use dbname; db.dropDatabase();
2. 操作集合
1.创建集合
切换到要操作的数据库,直接插入数据;会自动创建集合;其中stu是集合。
use school; db.stu.insert({name: "lyra"}); db.stu.insert({_id: 1, name: "lyra1"});
2. 创建集合2
db.createCollection('stu')
3. 操作文档
1. 插入文档
插入多条数据
> db.stu.find(); { "_id" : 1, "name" : "lyraLee", "hobbies" : [ "drawing", "drinking", "smoking" ] } > db.stu.insert([{_id:2, age:2}, {_id: 3, age: 3}]) BulkWriteResult({ "writeErrors" : [ ], "writeConcernErrors" : [ ], "nInserted" : 2, "nUpserted" : 0, "nMatched" : 0, "nModified" : 0, "nRemoved" : 0, "upserted" : [ ] }) > db.stu.find(); { "_id" : 1, "name" : "lyraLee", "hobbies" : [ "drawing", "drinking", "smoking" ] } { "_id" : 2, "age" : 2 } { "_id" : 3, "age" : 3 }
2. 更新文档(整条内容替换)
db.stu.save({_id: 1, name: "lyra1"});
3. 查看集合下所有文档内容
db.stu.find();
查看指定的文档
db.stu.find(<query>);
4. 删除集合
db.stu.drop();
4. 更新文档
- query: 查询条件; 如果是{}, 则表示更新所有的数据。
- updateObj: 更新体
- upsert: update/insert; 为true时表示,查询条件匹配则更新;不匹配则插入
- multi: 为true时表示同时变更所有的数据
db.collection.update(
<query>,
<updateObj>, {
upsert: true, multi: true } }
eg:
> db.stu.find(); { "_id" : 1, "name" : "lyraLee" } > db.stu.update({_id: 2}, {age: 1}) WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 }) > db.stu.update({_id: 2}, {age: 1}, {upsert: true}) WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : 2 }) > db.stu.find(); { "_id" : 1, "name" : "lyraLee" } { "_id" : 2, "age" : 1 }
5. 更新(update)操作符
1. $set- 只修改指定字段,其他字段保持不变
> db.stu.find({_id:1}); { "_id" : 1, "name" : "lyraLee", "age" : 1 } > db.stu.update({_id: 1}, {$set:{age: 18}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.stu.find({_id:1}); { "_id" : 1, "name" : "lyraLee", "age" : 18 }
2. $inc-执行字段增加
> db.stu.find({_id:1}); { "_id" : 1, "name" : "lyraLee", "age" : 18 } > db.stu.update({_id: 1}, {$inc:{age: 1}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.stu.find({_id:1}); { "_id" : 1, "name" : "lyraLee", "age" : 19 }
3. $unset-删除指定字段
> db.stu.find({_id:1}); { "_id" : 1, "name" : "lyraLee", "age" : 19 } > db.stu.update({_id: 1}, {$unset:{age: 1}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.stu.find({_id:1}); { "_id" : 1, "name" : "lyraLee" }
4. $push-添加数组数据(数据数据可能会重复)
> db.stu.find({_id:1}); { "_id" : 1, "name" : "lyraLee" } > db.stu.update({_id:1}, {$push:{hobbies:'swimming'}}); WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.stu.find({_id:1}); { "_id" : 1, "name" : "lyraLee", "hobbies" : [ "swimming" ] } > db.stu.update({_id:1}, {$push:{hobbies:'swimming'}}); WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.stu.find({_id:1}); { "_id" : 1, "name" : "lyraLee", "hobbies" : [ "swimming", "swimming" ] }
5. $ne-NotEqual限制数组的重复添加
> db.stu.find({_id:1}); { "_id" : 1, "name" : "lyraLee", "hobbies" : [ "swimming" ] } > db.stu.update({_id:1, hobbies:{$ne: 'swimming'}}, {$push:{hobbies:'swimming'}}); WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 }) > db.stu.find({_id:1}); { "_id" : 1, "name" : "lyraLee", "hobbies" : [ "swimming" ] }
6.$addToSet-添加不重复数据的数组(集合)
> db.stu.find({_id:1}); { "_id" : 1, "name" : "lyraLee", "hobbies" : [ "swimming" ] } > db.stu.update({_id:1}, {$addToSet:{hobbies:'swimming'}}); WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 }) > db.stu.find({_id:1}); { "_id" : 1, "name" : "lyraLee", "hobbies" : [ "swimming" ] } > db.stu.update({_id:1}, {$addToSet:{hobbies:'singing'}}); WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.stu.find({_id:1}); { "_id" : 1, "name" : "lyraLee", "hobbies" : [ "swimming", "singing" ] }
7. $pop-删除数组的最后一个数
> db.stu.find({_id:1}); { "_id" : 1, "name" : "lyraLee", "hobbies" : [ "swimming", "singing" ] } > db.stu.update({_id:1}, {$pop:{hobbies:1}}); WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > > db.stu.find({_id:1}); { "_id" : 1, "name" : "lyraLee", "hobbies" : [ "swimming" ] }
8.$each-合并数组元素
> db.stu.find({_id:1}); { "_id" : 1, "name" : "lyraLee", "hobbies" : [ "swimming" ] } > var arr = ['drinking', 'smoking']; > db.stu.update({_id:1}, {$addToSet:{hobbies:{$each: arr}}}); WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })> db.stu.find({_id:1}); { "_id" : 1, "name" : "lyraLee", "hobbies" : [ "swimming", "drinking", "smoking" ] }
9. 修改指定索引的值
> db.stu.find({_id:1}); { "_id" : 1, "name" : "lyraLee", "hobbies" : [ "swimming", "drinking", "smoking" ] } > db.stu.update({_id:1}, {$set:{'hobbies.0': 'drawing'}}); WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.stu.find({_id:1}); { "_id" : 1, "name" : "lyraLee", "hobbies" : [ "drawing", "drinking", "smoking" ] }
6. 删除文档
基本语法:
- collection_name 集合名称
db.collection_name.remove( <query>, { justOne: <boolean> } )
删除所有匹配条件的数据
> db.stu.find(); { "_id" : 1, "name" : "lyraLee", "hobbies" : [ "drawing", "drinking", "smoking" ] } { "_id" : 2, "age" : 1 } > db.stu.remove({age: 1}) WriteResult({ "nRemoved" : 1 }) > db.stu.find(); { "_id" : 1, "name" : "lyraLee", "hobbies" : [ "drawing", "drinking", "smoking" ] }
justOne只删除匹配条件的第一条数据
> db.stu.find(); { "_id" : 1, "name" : "lyraLee", "hobbies" : [ "drawing", "drinking", "smoking" ] } { "_id" : 2, "age" : 2 } { "_id" : 3, "age" : 2 } > db.stu.remove({age:2}, {justOne: true}) WriteResult({ "nRemoved" : 1 }) > db.stu.find(); { "_id" : 1, "name" : "lyraLee", "hobbies" : [ "drawing", "drinking", "smoking" ] } { "_id" : 3, "age" : 2 }
7. 查询文档操作符
1. find-查询出所有满足条件的数据(最多20条)
基本语法
- collection_name: 集合名称
- query: 查询条件
- key: 指定特定的列
- 0: exclusion 不包含该列
- 1: inclusion; 包含该列
db.collection_name.find( <query>, { key: 0/1 } )
⚠️: 0/1不能混用;即不能同时存在(_id除外)
示例: 返回指定的列
> db.stu.find(); { "_id" : 1, "name" : "lyraLee", "hobbies" : [ "drawing", "drinking", "smoking" ] } { "_id" : 3, "age" : 2 } > db.stu.find({_id:1}, {name:1, _id:0}); { "name" : "lyraLee" }
2. findone-查询出满足条件的第一条数据
> db.stu.find(); { "_id" : 1, "name" : "lyraLee", "hobbies" : [ "drawing", "drinking", "smoking" ] } { "_id" : 3, "age" : 2 } { "_id" : ObjectId("5e4ca86e925de31003f5cfbe"), "sex" : "female" } { "_id" : ObjectId("5e4ca885925de31003f5cfbf"), "sex" : "female" } > db.stu.findOne({sex: 'female'}) { "_id" : ObjectId("5e4ca86e925de31003f5cfbe"), "sex" : "female" }
3. $in- 包含
> db.stu.find(); { "_id" : 1, "age" : 1 } { "_id" : 2, "age" : 2 } { "_id" : 3, "age" : 3 } { "_id" : 4, "age" : 4 } { "_id" : 5, "age" : 5 } > db.stu.find({age: {$in: [2,4]}}) { "_id" : 2, "age" : 2 } { "_id" : 4, "age" : 4 }
4. $nin- 不包含
> db.stu.find({age: {$nin: [2,4]}}) { "_id" : 1, "age" : 1 } { "_id" : 3, "age" : 3 } { "_id" : 5, "age" : 5 }
5. $gte - greater than Or equal
$lte - less than Or equal
$lt - less than
$gt - greater than
> db.stu.find({age: {$gte: 2, $lte: 4}}) { "_id" : 2, "age" : 2 } { "_id" : 3, "age" : 3 } { "_id" : 4, "age" : 4 }
6. $not - 取反
> db.stu.find({age:{$not: {$gte: 2, $lte: 4}}}) { "_id" : 1, "age" : 1 } { "_id" : 5, "age" : 5 }
7. 查询数组
- 包含数组中的某一个值
> db.stu.find() { "_id" : 1, "age" : 1, "hobbies" : [ "A", "B", "C" ] } { "_id" : 2, "age" : 2, "hobbies" : [ "A" ] } { "_id" : 3, "age" : 3, "hobbies" : [ "B" ] } { "_id" : 4, "age" : 4, "hobbies" : [ "A", "B" ] } { "_id" : 5, "age" : 5, "hobbies" : [ "C" ] } > db.stu.find({hobbies: 'A'}) { "_id" : 1, "age" : 1, "hobbies" : [ "A", "B", "C" ] } { "_id" : 2, "age" : 2, "hobbies" : [ "A" ] } { "_id" : 4, "age" : 4, "hobbies" : [ "A", "B" ] }
- $all-同时包含数组中的某些值
> db.stu.find({hobbies: {$all: ['A','B']}}) { "_id" : 1, "age" : 1, "hobbies" : [ "A", "B", "C" ] } { "_id" : 4, "age" : 4, "hobbies" : [ "A", "B" ] }
- $in-包含其中任意一个值
> db.stu.find({hobbies: {$in: ['A','B']}}) { "_id" : 1, "age" : 1, "hobbies" : [ "A", "B", "C" ] } { "_id" : 2, "age" : 2, "hobbies" : [ "A" ] } { "_id" : 3, "age" : 3, "hobbies" : [ "B" ] } { "_id" : 4, "age" : 4, "hobbies" : [ "A", "B" ] }
- $size-按数组长度查询
> db.stu.find({hobbies: {$size:2}}) { "_id" : 4, "age" : 4, "hobbies" : [ "A", "B" ] }
- $slice-返回数组的部分数据
> db.stu.find({_id:1}, {hobbies: {$slice: 2}}) { "_id" : 1, "age" : 1, "hobbies" : [ "A", "B" ] } > db.stu.find({_id:1}, {hobbies: {$slice: -2}}) { "_id" : 1, "age" : 1, "hobbies" : [ "B", "C" ] }
8. $where-查询条件语句(查询速度慢)
> db.stu.find({$where: "this.age>2 && this.age<4"}) { "_id" : 3, "age" : 3, "hobbies" : [ "B" ] }
8. 查询方法
1. cursor
find()方法返回一个结果集(最多返回20条),可以通过其逐条查询
- cursor.hasNext():返回布尔值
- cursor.next(): 下一条数据
- printjson(data): 打印数据
> var cursor = db.stu.find(); > while(cursor.hasNext()) { printjson(cursor.next()); } { "_id" : 1, "age" : 1, "hobbies" : [ "A", "B", "C" ] } { "_id" : 2, "age" : 2, "hobbies" : [ "A" ] } { "_id" : 3, "age" : 3, "hobbies" : [ "B" ] } { "_id" : 4, "age" : 4, "hobbies" : [ "A", "B" ] } { "_id" : 5, "age" : 5, "hobbies" : [ "C" ] }
2. count()
返回结果集的条数
> db.stu.count(); 30
3. 正则表达式查询
> db.stu.find({name: /^my/}) { "_id" : 1, "name" : "mynameishehe" }
4. 逻辑与或(and/or)
-and
> db.stu.find({age: {$gte: 2, $lte: 4}}) { "_id" : 2, "age" : 2 } { "_id" : 3, "age" : 3 } { "_id" : 4, "age" : 4 }
-$or
> db.stu.find({$or: [{_id: {$lte: 2}}, {_id: {$gte: 4} }]}) { "_id" : 1, "name" : "mynameishehe" } { "_id" : 2, "age" : 2, "hobbies" : [ "A" ] } { "_id" : 4, "age" : 4, "hobbies" : [ "A", "B" ] } { "_id" : 5, "age" : 5, "hobbies" : [ "C" ] }
5. 分页查询
skip()- 跳过的数据条数;即(pageNum-1)*pageSize
limit(num)- 限制返回的数据条数; 即pageSize
sort({key: 1/-1})- 按照key排序;其中1表示正序;-1表示倒序
/**示例:返回排序后的第二页(pageSize=3)**/ > db.stu.find(); { "_id" : 1, "age" : 1 } { "_id" : 2, "age" : 2 } { "_id" : 3, "age" : 3 } { "_id" : 4, "age" : 4 } { "_id" : 5, "age" : 5 } { "_id" : 6, "age" : 6 } /**按照age字段正序排序后取第二页**/ > db.stu.find().skip((2-1)*3).limit(3).sort({age:1}) { "_id" : 4, "age" : 4 } { "_id" : 5, "age" : 5 } { "_id" : 6, "age" : 6 } /**按照age字段倒序排序后取第二页,**/ > db.stu.find().sort({age: -1}).skip((2-1)*3).limit(3) { "_id" : 3, "age" : 3 } { "_id" : 2, "age" : 2 } { "_id" : 1, "age" : 1 }
4. MongoDB数据库的备份和恢复
mongo/mongodump/mongorestore都是全局命令
1. 备份
/**备份后的文件位于命令运行时所在文件夹下***/ $ mongodump --out './bk' --collection stu --db test
2. 从备份的数据恢复
$ mongorestore './bk'
5. 执行脚本
mongo 文件名
示例:脚本内容-insert.js
var start = Date.now(); var users = []; for(let i=0; i<10000; i++) { users.push({_id: i, name: 'lyra'+i, age: i}); } db.stu.insert(users); /**批量插入;提高效率 **/ var cost = Date.now() - start; print(cost + 'ms');
运行脚本
$ mongo insert.js MongoDB shell version v4.2.3 connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb Implicit session: session { "id" : UUID("0587a441-5c94-4166-8634-4e1e2ea3c8cd") } MongoDB server version: 4.2.3 35ms