0%

MongoDB 学习笔记

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

使环境变量生效,

1
source ~/.bashrc

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:"齐天大圣,唐僧的徒弟"});
  • json 对象数组的形式插入多个文档

命令,

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
db.npc.find({age:300}) 

返回,

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()

返回,

1
2

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" : "妖精" }
  • 如果需要修改指定的属性,使用 $set
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" : "天蓬元帅" }
  • 如果需要删除指定的属性,使用 $unset
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

  • 修改一个符合条件的文档
  • update 默认

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 的顺序可以任意调换,但是实际执行的顺序依次是:
1
sort    =>    skip    =>    limit

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 一对多

  • 开发中常见的关系,例子:
1 n
父亲 孩子
用户 订单
文章 评论
  • 也可以通过内嵌文档的形式映射一对多的关系,比如在订单表中加一个字段,指向用户表中的某一个用户
  • 通常是在 “多” 的一方的表中加一个字段

6.3 多对多

  • 新建一个文档用来表示多对多的关系,字段是关系双方的 id
  • 例如,学生和选课是多对多的关系,一个学生可以选择多门课,一个课程可以被多个学生选,存在课程表和学生表,则选课关系如下:
id course_id student_id