MongoDB 学习笔记
1 MongoDB 简介
1.1 数据库的分类
1.1.1 关系型数据库(RDBMS)
- MySQL、Oracle、SQL Server、DB2 ……
- 关系数据库中全部是表(所谓“关系”,通俗点说就是二维表)
1.1.2 非关系型数据库(NoSQL)
- NoSQL是Not Only SQL的缩写,“不仅仅是SQL”
- Redis:键值对数据库,常用作缓存
- MongoDB:文档数据库
1.2 MongoDB 概述
MongoDB 的数据模型是面向文档的,所谓文档是一种类似于JSON的结构,简单理解 MongoDB 数据库中存的是各种各样的JSON(BSON)。
2 MongoDB 安装
2.1 安装依赖包
1
| sudo apt-get install libcurl3 openssl
|
2.2 下载、解压、移动文件
1
| wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-debian92-5.0.2.tgz
|
1
| tar -xzvf mongodb-linux-x86_64-debian92-5.0.2.tgz
|
1
| mv mongodb-linux-x86_64-debian92-5.0.2 /opt/mongodb
|
2.3 配置环境变量
在 ~/.bashrc 文件中添加一行:
1
| export PATH=$PATH:/opt/mongodb/bin
|
使环境变量生效,
3 MongoDB 服务启动、停止
3.1 前台启动
1
| mongod --dbpath <数据存储目录>
|
3.2 后台启动
1
| mongod --dbpath <数据存储目录> --logpath <日志文件路径> --fork
|
3.3 停止服务
1
| mongod --dbpath <数据存储目录> --logpath <日志文件路径> --shutdown
|
4 基本使用
4.1 数据库对象
- 数据库:是一个仓库,可以存放多个集合。
- 集合:类似于数组,可以存放多个文档。
- 文档:数据库中的最小单位,我们存储和操作的内容都是文档。
4.2 常用命令
命令 |
功能 |
show databases |
显示所有的数据库 |
use <数据库名> |
切换数据库(支持自动创建数据库) |
db |
显示当前所处的数据库 |
show collections |
显示当前数据库中所有的集合 |
db.<集合名>.insert(<文档内容>) |
向集合中插入文档 |
db.<集合名>.find() |
查询集合中的文档 |
5 CRUD
5.1 插入文档
5.1.1 ObjectId
- 当插入文档时,如果没有显式地给出 “_id” 字段值,则 MongoDB 会自动为文档生成一个独一无二的 “_id” 字段值。
1
| { "_id" : ObjectId("6141e9058a2bd158b67c5a70"), "name" : "孙悟空", "age" : 500, "description" : "齐天大圣,唐僧的徒弟" }
|
5.1.2 insert
- 在集合中插入一个或多个文档
- 以 json 对象的形式插入一个文档
1
| db.npc.insert({name:"孙悟空", age:500, description:"齐天大圣,唐僧的徒弟"});
|
命令,
1
| db.npc.insert([{name:"猪八戒", age:300, description:"天蓬元帅"}, {name:"沙悟净", age:200, description:"卷帘大将"}]);
|
返回,
1 2 3 4 5 6 7 8 9 10
| BulkWriteResult({ "writeErrors" : [ ], "writeConcernErrors" : [ ], "writeConcernErrors" : [ ], "writeErrors" : [ ], "writeConcernErrors" : [ ], "nInserted" : 2, "nUpserted" : 0, "nMatched" : 0, "nModified" : 0, "nRemoved" : 0, "upserted" : [ ] })
|
5.1.3 insertOne
命令,
1
| db.npc.insertOne({name:"唐僧", age: 800, description:"金蝉子"});
|
返回,
1 2 3 4
| { "acknowledged" : true, "insertedId" : ObjectId("61420315cb3a9ab2eb5a6975") }
|
5.1.4 insertMany
命令,
1
| db.npc.insertMany([{name:"蜘蛛精", age:400, description:"妖精"}, {name:"白骨精", age:300, description:"妖精"}]);
|
返回,
1 2 3 4 5 6 7
| { "acknowledged" : true, "insertedIds" : [ ObjectId("614206cec4c4d45fc611c481"), ObjectId("614206cec4c4d45fc611c482") ObjectId("614206cec4c4d45fc611c482") ObjectId("614206cec4c4d45fc611c481"), ObjectId("614206cec4c4d45fc611c482") ] }
|
5.2 查询文档
5.2.1 db.collection.find
- 查询集合中符合条件的文档,返回的是一个结果数组
- 传入一个对象作为筛选条件
- 例如:
查询,
返回,
1 2
| { "_id" : ObjectId("6142027bcb3a9ab2eb5a6973"), "name" : "猪八戒", "age" : 300, "description" : "天蓬元帅" } { "_id" : ObjectId("614206cec4c4d45fc611c482"), "name" : "白骨精", "age" : 300, "description" : "妖精" }
|
5.2.2 db.collection.findOne
- 查询集合中符合条件的第一个文档,返回的是一个对象
- 例如:
查询,
1
| db.npc.findOne({age:300})
|
返回,
1 2 3 4 5
| { "_id" : ObjectId("6142027bcb3a9ab2eb5a6973"), "name" : "猪八戒", "age" : 300, "description" : "天蓬元帅" }
|
5.2.3 db.collection.find.count
查询,
1
| db.npc.find({age:300}).count()
|
返回,
5.3 修改文档
5.3.1 db.collection.update
1
| db.<集合名>.update(<查询条件>, <修改/新对象>, <选项>)
|
- 默认情况下,会使用新对象来替换旧对象,注意:新对象直接替换旧对象,不保留原对象的值。
1 2 3 4 5
| > db.npc.update({age:300}, {name:"猪八戒", age:300, address:"高老庄"}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.npc.find({age:300}) { "_id" : ObjectId("6142027bcb3a9ab2eb5a6973"), "name" : "猪八戒", "age" : 300, "address" : "高老庄" } { "_id" : ObjectId("614206cec4c4d45fc611c482"), "name" : "白骨精", "age" : 300, "description" : "妖精" }
|
1 2 3 4
| > db.npc.update({name:"猪八戒"}, {$set:{description:"天蓬元帅"}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.npc.find({name:"猪八戒"}) { "_id" : ObjectId("6142027bcb3a9ab2eb5a6973"), "name" : "猪八戒", "age" : 300, "address" : "高老庄", "description" : "天蓬元帅" }
|
1 2 3 4
| > db.npc.update({name:"猪八戒"}, {$unset:{address:""}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.npc.find({name:"猪八戒"}) { "_id" : ObjectId("6142027bcb3a9ab2eb5a6973"), "name" : "猪八戒", "age" : 300, "description" : "天蓬元帅" }
|
- update 默认只会修改一个,设置选项 multi: true,可支持修改多个文档对象
1 2 3 4 5
| > db.npc.update({description:"妖精"}, {$set:{gender:"女"}}, {multi:true}) WriteResult({ "nMatched" : 2, "nUpserted" : 0, "nModified" : 2 }) > db.npc.find({description:"妖精"}) { "_id" : ObjectId("614206cec4c4d45fc611c481"), "name" : "蜘蛛精", "age" : 400, "description" : "妖精", "gender" : "女" } { "_id" : ObjectId("614206cec4c4d45fc611c482"), "name" : "白骨精", "age" : 300, "description" : "妖精", "gender" : "女" }
|
5.3.2 db.collection.updateMany
- 同时修改多个符合条件的文档
- 相当于 update 设置选项 multi: true
5.3.3 db.collection.updateOne
5.3.4 db.collection.replaceOne
5.4 删除文档
5.4.1 db.collection.remove
1 2 3 4
| db.collection.remove( <query>, <justOne> )
|
- 根据条件来删除文档,传递条件的方式和 find() 一样
- 默认情况下会删除多个
- 第二个参数传递 true,则只会删除一个
5.4.2 db.collection.deleteOne
5.4.3 db.collection.deleteMany
5.4.4 db.collection.drop
5.4.5 db.dropDatabase
5.5 sort、limit、skip
5.5.1 sort
- 查询文档时,默认情况是按照 _id 的值进行排列(升序)
- sort 可以用来指定文档排序的规则
- 需要传递一个对象用来指定排序的规则,1 表示升序,-1 表示降序
- 例如 employee 对象中有一字段 salary,要求按照工资升序排列,
1
| db.employees.find().sort({salary:1})
|
5.5.2 limit
- 取出集合中前 n 个文档
- 例如,查询职工表中前两个职工,
1
| db.employees.find().limit(2)
|
5.5.3 skip
- 跳过集合中前 n 个文档
- 例如,查询职工表中从第 3 个开始的所有职工,
1
| db.employees.find().skip(2)
|
5.5.4 调用顺序
- 以上三个函数可以组合使用,代码中 sort、limit、skip 的顺序可以任意调换,但是实际执行的顺序依次是:
5.6 投影
- 查询时,可以在第二个参数位置来设置查询结果的投影
- 例如,查询所有职工的姓名和工资,
1
| db.employees.find({}, {name:1, salary:1})
|
- 默认情况下,会显示 _id 字段,可设置 _id: 0 去除
1
| db.employees.find({}, {name:1, salary:1, _id:0})
|
6 文档之间的关系
6.1 一对一
- 使用内嵌文档的形式表示,其实就是在其中一个文档中加一个引用字段
6.2 一对多
- 也可以通过内嵌文档的形式映射一对多的关系,比如在订单表中加一个字段,指向用户表中的某一个用户
- 通常是在 “多” 的一方的表中加一个字段
6.3 多对多
- 新建一个文档用来表示多对多的关系,字段是关系双方的 id
- 例如,学生和选课是多对多的关系,一个学生可以选择多门课,一个课程可以被多个学生选,存在课程表和学生表,则选课关系如下: