MongoDB简介

是什么

  • 基于分布犹文件存储数据库(就是一个数据库
  • C++语言编写
  • 支持的数据结构非常松散,是类似json的bson格式(后期插入修改数据写JSON)

JSON(JavaScript Object Notation,JS对象简谱)是一种轻量级的数据交换格式bson(二进制SON)

能干嘛

  • 存放项目数据

  • 实战工作开发写API接口(重要

  • 等等

从哪下载

版本说明

  • 2.x
  • 3.x (3.2、 3.4、 3.6)
  • 4.x (4.2更佳的数据管理能力、更强的分布式架构、多文档事物等)
  • 写这篇教程的时候最新版是 4.4

安装

Liunx系统

1
2
3
4
5
6
7
8
9
10
11
12
13
#步骤1:下载
curl -o https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.0.6.tgz
#步骤2:解压
tar -zxvf mongodb-linux-x86_64-3.0.6.tgz
#步骤3:将解压包拷贝到指定目录
mv mongodb-linux-x86_64-3.0.6/ /usr/local/mongodb
#步骤4:创建数据存放目录与日志存放目录
mkdir -p /usr/local/mongodb/data /usr/local/mongodb/logs
#步骤5:启动MongoDB服务
/usr/local/mongodb/bin/mongod -- dbpath=/usr/local /mongodb/data --logpath=/usr/local/mongodb/logs/mongodb.log --logappend --port=27017 --fork

#后期登录即可
/usr/local/mongodb/bin/mongo

Win系统

步骤1: 下载 https://www.mongodb.com/download-center/community 选择windows、zip
步骤2: 解压
步骤3: 创建服务

1
bin/mongod.exe --install --dbpath 磁盘路径 --logpath 日志路径

注意:

  • 通过管理员身份运行DOS窗口否则没有权限创建失败
  • 需要提前创建数据和日志存放目录、比如在bin同级目录下创建data 、logs目录

这是我的命令:

1
D:\Programs\MongoDB\bin>mongod --install --dbpath D:\Programs\MongoDB\data --logpath D:\Programs\MongoDB\logs\mongodb.log

步骤4: 启动服务

可以在windows中的服务中找到MongDB

1
net start mongodb

步骤5: 登录(验证是否安装成功)

输入mongo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
D:\Programs\MongoDB\bin>mongo
MongoDB shell version v4.4.0
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("96b8ce39-895f-40eb-93a4-afd64c26c1cf") }
MongoDB server version: 4.4.0
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
https://docs.mongodb.com/
Questions? Try the MongoDB Developer Community Forums
https://community.mongodb.com
---
The server generated these startup warnings when booting:
2020-08-21T11:02:34.822+08:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted
2020-08-21T11:02:34.823+08:00: This server is bound to localhost. Remote systems will be unable to connect to this server. Start the server with --bind_ip <address> to specify which IP addresses it should serve responses from, or with --bind_ip_all to bind to all interfaces. If this behavior is desired, start the server with --bind_ip 127.0.0.1 to disable this warning
---
---
Enable MongoDB's free cloud-based monitoring service, which will then receive and display
metrics about your deployment (disk utilization, CPU, operation statistics, etc).

The monitoring data will be available on a MongoDB website with a unique URL accessible to you
and anyone you share the URL with. MongoDB may use this information to make product
improvements and to suggest MongoDB products and deployment options to you.

To enable free monitoring, run the following command: db.enableFreeMonitoring()
To permanently disable this reminder, run the following command: db.disableFreeMonitoring()
---
> exit
bye

基本语法

  • 创建服务: bin/mongod. exe --install -- dbpath 磁盘路径 -- logpath 日志路径
  • 删除服务: bin/mongod. exe --remove
  • 启动服务: net start mongodb (注: service 服务名d restart/stop/start)
  • 关闭服务: net stop mongodb

基本操作

基本概念

  • 生活中:仓库、架子、物品
  • 计算机:数据库(database) 、集合(collection) 、数据/文档(document)

查看数据库

语法:show databases缩写:show dbs

效果:

选择数据库

语法: use 数据库名

1
2
3
4
> use admin
switched to db admin
> use admin2
switched to db admin2

隐式创建: 在mongodb选择不存在的数据库不会报错,后期当该数据库有数据时,系统自动创建

查看集合

语法: show collections

1
2
3
4
5
> use admin
switched to db admin
> show collections
system.version
>

创建集合

语法: db.createCollection("集合名")

1
2
3
4
5
6
7
> use zykj
switched to db zykj
> db.createCollection('c1')
{ "ok" : 1 }
> show collections
c1
>

删除集合

语法: db.集合名.drop()

1
2
3
4
5
6
> show collections
c1
> db.c1.drop()
true
> show collections
>

思考:如何删除数据库?
回答:

  1. 通过use语法选中数据库
  2. 通过db.dropDatabase()

小总结

数据库(查看、创建、选择、删除

1
2
3
4
查看: show databases
创建: 有单独的语法,但是忽略 隐式创建
选择: use数据库名
删除: 1通过use选中数据库,2通过db.dropDatabase()删除数据库

集合(查看、创建、删除

1
2
3
查看: show collections
创建: db.createcollection('集合名') 多学一招:忽略﹐后期插入数据隐式创建集合
删除: db.集合名.drop()

文档增删改查(CURD)

明确需求

数据库主要用来存放项目数据
然后我们已经学会了数据库和集合的创建

思考: 如何实现集合中数据的增删改查呢?
回答: 通过MongoDB语法即可

增 C

语法: db.集合名.insert(JSON数据)
说明: 集合存在-则直接插入数据,集合不存在-隐式创建
练习: 在test2数据库的c1集合中插入数据(姓名叫webopenfather年龄18岁)

1
2
3
4
5
6
use test2
db.c1.insert({uname : "webopenfather", age:18})

留心1:数据库和集合不存在都隐式创建
留心2:对象的键统一不加引号方便看,但是查看集合数据时系统会自动加
留心3: mongodb会给每条数据增加一个全球唯一的_id键

结果:

1
2
3
4
5
6
7
> use test2
switched to db test2
> db.c1.insert({uname:"webopenfather",age:18})
WriteResult({ "nInserted" : 1 })
> db.c1.find()
{ "_id" : ObjectId("5f3f90760125df8cc59a60a6"), "uname" : "webopenfather", "age" : 18 }
>

多学一招:_id的组成:时间戳+机器码+PID+计数器

思考1: 是否可以自定义_id值?

回答:可以,只需要给插入的SON数据增加_id键即可覆盖(但实战强烈不推荐
db.c1.insert({_id:1, uname:"webopenfather", age:18})

思考2: 如何一次性插入多条记录?

回答:传递数据,数组中写一个个JSON数据即可

1
2
3
4
5
6
7
db.c1.insert([
{uname: "z3",age: 3},
{uname: "z4",age:4},
{uname : "w5",age: 5}
])

含义:—次性插入3条数据到c1集合

思考3:如何快速插入10条数据

回答: mongodb底层使用JS引擎实现的,所以支持部分js语法
因此: 可以写for循环

1
2
3
for (var i=1; i<=10; i++){
print(i)
}

需求:在test2数据库c2集合中插入10条数据,分别为a1 a2 … a10

1
2
3
4
use test2
for(var i=1;i<=10;i++){
db.c2.insert({uname: "a"+i, age: i})
}

结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
> for(var i=1;i<=10;i++){
... print(i)
... }
1
2
3
4
5
6
7
8
9
10
> for(var i=1;i<=10;i++){
... db.c2.insert({uname: "a"+i ,age: i})
... }
WriteResult({ "nInserted" : 1 })
> db.c2.find()
{ "_id" : ObjectId("5f3f99e38a803b8b630d59b3"), "uname" : "a1", "age" : 1 }
{ "_id" : ObjectId("5f3f99e38a803b8b630d59b4"), "uname" : "a2", "age" : 2 }
{ "_id" : ObjectId("5f3f99e38a803b8b630d59b5"), "uname" : "a3", "age" : 3 }
{ "_id" : ObjectId("5f3f99e38a803b8b630d59b6"), "uname" : "a4", "age" : 4 }
{ "_id" : ObjectId("5f3f99e38a803b8b630d59b7"), "uname" : "a5", "age" : 5 }
{ "_id" : ObjectId("5f3f99e38a803b8b630d59b8"), "uname" : "a6", "age" : 6 }
{ "_id" : ObjectId("5f3f99e38a803b8b630d59b9"), "uname" : "a7", "age" : 7 }
{ "_id" : ObjectId("5f3f99e38a803b8b630d59ba"), "uname" : "a8", "age" : 8 }
{ "_id" : ObjectId("5f3f99e38a803b8b630d59bb"), "uname" : "a9", "age" : 9 }
{ "_id" : ObjectId("5f3f99e38a803b8b630d59bc"), "uname" : "a10", "age" : 10 }
>
>

查 R

基础语法: db.集合名.find(条件[,查询的列])

条件

  • 查询所有数据
  • 或者不写
  • 查询age=6的数据 {age:6}
  • 既要age=6又要性别=男 {age:6 ,sex:’男’}

查询的列(可选参数

  • 不写 – 这查询全部列 (字段
  • {age:1} 共显示age列 (字段
  • {age:0} 除了age (字段都显示
  • 留心:不管你怎么写系统自定义的 _id 都会在

升级语法:

1
2
3
4
5
6
db.集合名.find({键:值})	注:值不直接写
{运算符:值}

db.集合名.find({
键:{运算符:值}
})
运算符作用
$gt大于
$gte大于等于
$lt小于
$lte小于等于
$ne不等于
$inin
$ninnot in

练习1:查询所有数据

1
2
3
4
5
6
7
8
9
10
11
12
> use test2
switched to db test2
> show collections
c1
c2
> db.c2.find({},{uname:1})
{ "_id" : ObjectId("5f3f99e38a803b8b630d59b3"), "uname" : "a1" }
{ "_id" : ObjectId("5f3f99e38a803b8b630d59b4"), "uname" : "a2" }
{ "_id" : ObjectId("5f3f99e38a803b8b630d59b5"), "uname" : "a3" }
> db.c2.find({},{uname:0})
{ "_id" : ObjectId("5f3f99e38a803b8b630d59b3"), "age" : 1 }
{ "_id" : ObjectId("5f3f99e38a803b8b630d59b4"), "age" : 2 }

练习2:查询年龄大于5岁的数据?

1
2
3
4
5
6
7
8
9
> db.c2.find({age:5})
{ "_id" : ObjectId("5f3f99e38a803b8b630d59b7"), "uname" : "a5", "age" : 5 }
> db.c2.find({age:{$gt:5}})
{ "_id" : ObjectId("5f3f99e38a803b8b630d59b8"), "uname" : "a6", "age" : 6 }
{ "_id" : ObjectId("5f3f99e38a803b8b630d59b9"), "uname" : "a7", "age" : 7 }
{ "_id" : ObjectId("5f3f99e38a803b8b630d59ba"), "uname" : "a8", "age" : 8 }
{ "_id" : ObjectId("5f3f99e38a803b8b630d59bb"), "uname" : "a9", "age" : 9 }
{ "_id" : ObjectId("5f3f99e38a803b8b630d59bc"), "uname" : "a10", "age" : 10 }
>

练习3:查询年龄是5岁、8岁、10岁的数据?

1
2
3
4
5
> db.c2.find({age:{$in:[5,8,10]}})
{ "_id" : ObjectId("5f3f99e38a803b8b630d59b7"), "uname" : "a5", "age" : 5 }
{ "_id" : ObjectId("5f3f99e38a803b8b630d59ba"), "uname" : "a8", "age" : 8 }
{ "_id" : ObjectId("5f3f99e38a803b8b630d59bc"), "uname" : "a10", "age" : 10 }
>

练习4:只看年龄列,或者年龄以外的列(_id别管它)?

1
2
3
4
5
6
7
8
9
10
> db.c2.find({},{age:1})
{ "_id" : ObjectId("5f3f99e38a803b8b630d59b3"), "age" : 1 }
{ "_id" : ObjectId("5f3f99e38a803b8b630d59b4"), "age" : 2 }
{ "_id" : ObjectId("5f3f99e38a803b8b630d59b5"), "age" : 3 }

> db.c2.find({},{age:0})
{ "_id" : ObjectId("5f3f99e38a803b8b630d59b3"), "uname" : "a1" }
{ "_id" : ObjectId("5f3f99e38a803b8b630d59b4"), "uname" : "a2" }
{ "_id" : ObjectId("5f3f99e38a803b8b630d59b5"), "uname" : "a3" }
>

改 U

基础语法: db.集合名.update(条件,新数据[,是否新增,是否修改多条])

1
2
是否新增:指条件匹配不到数据则插入(true是插入,false否不插入默认)
是否修改多条:指将匹配成功的数据都修改(true是,false否默认)

升级语法:

1
2
db.集合名.update(条件,新数据)
{修改器: {键:值}}
运算符作用
$inc递增
$netame重命名列
$set修改列值
$unset删除列

准备工作

1
2
3
4
use test2;
for(var i = 1; i<= 10; i++){
db.c3.insert( {"uname":"zs"+i, "age":i});
}

练习1:将{uname:"zs1"}改为{uname:"zs2"}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
> db.c3.update({uname:"zs1"},{uname:"zs2"})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.c3.find()
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f6"), "uname" : "zs2" }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f7"), "uname" : "zs2", "age" : 2 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f8"), "uname" : "zs3", "age" : 3 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f9"), "uname" : "zs4", "age" : 4 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fa"), "uname" : "zs5", "age" : 5 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fb"), "uname" : "zs6", "age" : 6 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fc"), "uname" : "zs7", "age" : 7 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fd"), "uname" : "zs8", "age" : 8 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fe"), "uname" : "zs9", "age" : 9 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4ff"), "uname" : "zs10", "age" : 10 }
>

发现: 默认不是修改,而是替换
解决:使用升级语法修改器

需求: 使用修改器将zs2的姓名改为zs22
语法: db.c3.update({uname:"zs2"}, {$set: {uname: "zs22"}})

1
2
3
4
5
6
7
8
9
10
11
12
13
14
> db.c3.update({uname:"zs2"},{$set:{uname:"zs22"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.c3.find()
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f6"), "uname" : "zs22" }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f7"), "uname" : "zs2", "age" : 2 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f8"), "uname" : "zs3", "age" : 3 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f9"), "uname" : "zs4", "age" : 4 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fa"), "uname" : "zs5", "age" : 5 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fb"), "uname" : "zs6", "age" : 6 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fc"), "uname" : "zs7", "age" : 7 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fd"), "uname" : "zs8", "age" : 8 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fe"), "uname" : "zs9", "age" : 9 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4ff"), "uname" : "zs10", "age" : 10 }
>

发现默认只能改一条数据

练习2: 给{uname:"zs10"}的年龄加2岁或者减2岁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
> db.c3.find()
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f6"), "uname" : "zs22" }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f7"), "uname" : "zs2", "age" : 2 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f8"), "uname" : "zs3", "age" : 3 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f9"), "uname" : "zs4", "age" : 4 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fa"), "uname" : "zs5", "age" : 5 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fb"), "uname" : "zs6", "age" : 6 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fc"), "uname" : "zs7", "age" : 7 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fd"), "uname" : "zs8", "age" : 8 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fe"), "uname" : "zs9", "age" : 9 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4ff"), "uname" : "zs10", "age" : 10 }
> db.c3.update({uname:"zs10"},{$inc:{age:2}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.c3.find()
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f6"), "uname" : "zs22" }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f7"), "uname" : "zs2", "age" : 2 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f8"), "uname" : "zs3", "age" : 3 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f9"), "uname" : "zs4", "age" : 4 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fa"), "uname" : "zs5", "age" : 5 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fb"), "uname" : "zs6", "age" : 6 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fc"), "uname" : "zs7", "age" : 7 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fd"), "uname" : "zs8", "age" : 8 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fe"), "uname" : "zs9", "age" : 9 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4ff"), "uname" : "zs10", "age" : 12 }
> db.c3.update({uname:"zs10"},{$inc:{age:-2}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.c3.find()
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f6"), "uname" : "zs22" }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f7"), "uname" : "zs2", "age" : 2 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f8"), "uname" : "zs3", "age" : 3 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f9"), "uname" : "zs4", "age" : 4 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fa"), "uname" : "zs5", "age" : 5 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fb"), "uname" : "zs6", "age" : 6 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fc"), "uname" : "zs7", "age" : 7 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fd"), "uname" : "zs8", "age" : 8 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fe"), "uname" : "zs9", "age" : 9 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4ff"), "uname" : "zs10", "age" : 10 }
>

练习3: 修改器综合练习
插入数据: db.c4.insert( {uname:"神龙教主",age:888,who:"男",other:"非国人"});

完成需求:
uname 改成 zykj (修改器: $set)
age 增加 111 (修改器: $inc)
who 改字段 sex (修改器: $netame)
other 删除 (修改器: $unset)

语法|分析:

1
2
3
4
5
6
7
8
9
10
11
12
13
db.c4.update( {uname :"神龙教主"},{uname: "zykj"}) #错误, 替换
{$set: {uname: "zykj"}}
{$inc: {age: 111}}
{$netame: {who: "sex"}}
{$unset: {other: true}}

留心如何一次性写多个修改器
db.c4.update( {uname: "神龙教主"},{
$set: {uname : "zykj"},
$inc: {age: 111},
$netame: {who: "sex"},
$unset: {other: true}
})

示例:

1
2
3
4
5
6
7
8
9
10
11
12
> db.c4.insert( {uname:"神龙教主",age:888,who:"男",other:"非国人"})
WriteResult({ "nInserted" : 1 })
> db.c4.update( {uname: "神龙教主"},{
... $set: {uname : "zykj"},
... $inc: {age: 111},
... $netame: {who: "sex"},
... $unset: {other: true}
... })
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.c4.find()
{ "_id" : ObjectId("5f3fd9c28989b2009f00b500"), "uname" : "zykj", "age" : 999, "sex" : "男" }
>

练习4: 验证语法最后两个参数(了解)
[验证]是否新增true是false否: 修改 uname 等于 zs30 的年龄 30岁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
> db.c3.find()
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f6"), "uname" : "zs22" }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f7"), "uname" : "zs2", "age" : 2 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f8"), "uname" : "zs3", "age" : 3 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f9"), "uname" : "zs4", "age" : 4 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fa"), "uname" : "zs5", "age" : 5 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fb"), "uname" : "zs6", "age" : 6 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fc"), "uname" : "zs7", "age" : 7 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fd"), "uname" : "zs8", "age" : 8 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fe"), "uname" : "zs9", "age" : 9 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4ff"), "uname" : "zs10", "age" : 12 }
> db.c3.update({name:"zs30"},{$set:{age:30}},false)
WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })
> db.c3.update({name:"zs30"},{$set:{age:30}},true)
WriteResult({
"nMatched" : 0,
"nUpserted" : 1,
"nModified" : 0,
"_id" : ObjectId("5f3fde2703673d79be111d2c")
})
> db.c3.find()
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f6"), "uname" : "zs22" }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f7"), "uname" : "zs2", "age" : 2 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f8"), "uname" : "zs3", "age" : 3 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f9"), "uname" : "zs4", "age" : 4 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fa"), "uname" : "zs5", "age" : 5 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fb"), "uname" : "zs6", "age" : 6 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fc"), "uname" : "zs7", "age" : 7 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fd"), "uname" : "zs8", "age" : 8 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fe"), "uname" : "zs9", "age" : 9 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4ff"), "uname" : "zs10", "age" : 12 }
{ "_id" : ObjectId("5f3fde2703673d79be111d2c"), "name" : "zs30", "age" : 30 }
>

[验证]是否修改多条true是, false否默认

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
> db.c3.update({},{$set:{age:10}},false,false)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.c3.update({},{$set:{age:20}},false,true)
WriteResult({ "nMatched" : 11, "nUpserted" : 0, "nModified" : 11 })
> db.c3.find()
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f6"), "uname" : "zs22", "age" : 20 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f7"), "uname" : "zs2", "age" : 20 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f8"), "uname" : "zs3", "age" : 20 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f9"), "uname" : "zs4", "age" : 20 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fa"), "uname" : "zs5", "age" : 20 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fb"), "uname" : "zs6", "age" : 20 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fc"), "uname" : "zs7", "age" : 20 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fd"), "uname" : "zs8", "age" : 20 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fe"), "uname" : "zs9", "age" : 20 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4ff"), "uname" : "zs10", "age" : 20 }
{ "_id" : ObjectId("5f3fde2703673d79be111d2c"), "name" : "zs30", "age" : 20 }
>

删 D

语法: db.集合名.remove(条件[,是否删除一条])
注意: 是否删除一条true是,false否、默认为false

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
> db.c3.find()
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f6"), "uname" : "zs22", "age" : 20 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f7"), "uname" : "zs2", "age" : 20 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f8"), "uname" : "zs3", "age" : 20 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4f9"), "uname" : "zs4", "age" : 20 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fa"), "uname" : "zs5", "age" : 20 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fb"), "uname" : "zs6", "age" : 20 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fc"), "uname" : "zs7", "age" : 20 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fd"), "uname" : "zs8", "age" : 20 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4fe"), "uname" : "zs9", "age" : 20 }
{ "_id" : ObjectId("5f3fd0a58989b2009f00b4ff"), "uname" : "zs10", "age" : 20 }
{ "_id" : ObjectId("5f3fde2703673d79be111d2c"), "name" : "zs30", "age" : 20 }
> db.c3.remove({},true)
WriteResult({ "nRemoved" : 1 })
> db.c3.remove({})
WriteResult({ "nRemoved" : 10 })
>

小总结

增Create

1
db.集合名.insert(JSON数据)

删Delete

1
2
3
db.集合名.remove(条件[是否删除一条true是false否默认])

也就是默认删除多条

改Update

1
2
3
db.集合名.update(条件,新数据 [,是否新增,是否修改多条] )

升级语法 db.集合名.update(条件, {修改器: {键: 值})

查Read

1
db.集合名.find(条件 [,查询的列])

教学管理系统数据库设计

图片中的字段:编号、学号、姓名、电话、性别、年龄、学历、备注

实战开发流程

数据库设计流程

根据UI设计稿

  1. 确定功能模块所属集合
  2. 确定集合字段
1
2
3
4
5
6
7
UI设计稿每个展示内容对应一个字段
创建于字段
更新于字段
状态字段

最后:先中文、再英文
留心:上述规则照顾基础差的,如果大神 或 久而久之 就变成肌肉记忆,下意识直接创建

练习

  • 需求:根据千锋教学系统,设置存放学生信息的集合,并插入20条测试数据
  • 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1.先中文
集合名称:学生集合
集合字段:编号、学好、姓名、电话、性别、年龄、学历、备注


2.再英文
use school
for (var num=1; num<=20;num++){
db.stu.insert({
id:num,
no: "QF"+num,
uname:"神龙教"+num,
tel: "1111111111",
sex:"女",
age: num,
schoo1:"研究生",
remark:"士豪"
})
}

示例:小知识: pretty() 可以格式化json字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
> use school
switched to db school
> for (var num=1; num<=2;num++){
... db.stu.insert({
... id:num,
... no: "QF"+num,
... uname:"神龙教"+num,
... tel: "1111111111",
... sex:"女",
... age: num,
... schoo1:"研究生",
... remark:"士豪"
... })
... }
WriteResult({ "nInserted" : 1 })
> db.stu.find()
{ "_id" : ObjectId("5f40804888a3d5009c18204f"), "id" : 1, "no" : "QF1", "uname" : "神龙教1", "tel" : "1111111111", "sex" : "女", "age" : 1, "schoo1" : "研究生", "remark" : "士豪" }
{ "_id" : ObjectId("5f40804888a3d5009c182050"), "id" : 2, "no" : "QF2", "uname" : "神龙教2", "tel" : "1111111111", "sex" : "女", "age" : 2, "schoo1" : "研究生", "remark" : "士豪" }
> db.stu.find().pretty()
{
"_id" : ObjectId("5f40804888a3d5009c18204f"),
"id" : 1,
"no" : "QF1",
"uname" : "神龙教1",
"tel" : "1111111111",
"sex" : "女",
"age" : 1,
"schoo1" : "研究生",
"remark" : "士豪"
}
{
"_id" : ObjectId("5f40804888a3d5009c182050"),
"id" : 2,
"no" : "QF2",
"uname" : "神龙教2",
"tel" : "1111111111",
"sex" : "女",
"age" : 2,
"schoo1" : "研究生",
"remark" : "士豪"
}
>

排序&分页

明确需求

数据库,是用来存放数据的
咱们后期从数据库获取数据需要排序、多页展示如何实现?

准备

1
2
3
4
5
6
7
8
use test3
db.c1.insert({_id:1,name:"a",sex:1,age:1})
db.c1.insert({_id:2,name:"a",sex:1,age:2})
db.c1.insert({_id:3,name:"b",sex:2,age:3})
db.c1.insert({_id:4,name:"c",sex:2,age:4})
db.c1.insert({_id:5,name:"d",sex:2,age:5})

db.c1.find()

排序

  • 语法: db.集合名.find().sort(JSON数据)
  • 说明: 键-就是要排序的列/字段、值:1升序 -1降序
  • 练习:年龄升序&降序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
> use test3
switched to db test3
> db.c1.insert({_id:1,name:"a",sex:1,age:1})
WriteResult({ "nInserted" : 1 })
> db.c1.insert({_id:2,name:"a",sex:1,age:2})
WriteResult({ "nInserted" : 1 })
> db.c1.insert({_id:3,name:"b",sex:2,age:3})
WriteResult({ "nInserted" : 1 })
> db.c1.insert({_id:4,name:"c",sex:2,age:4})
WriteResult({ "nInserted" : 1 })
> db.c1.insert({_id:5,name:"d",sex:2,age:5})
WriteResult({ "nInserted" : 1 })
> db.c1.find()
{ "_id" : 1, "name" : "a", "sex" : 1, "age" : 1 }
{ "_id" : 2, "name" : "a", "sex" : 1, "age" : 2 }
{ "_id" : 3, "name" : "b", "sex" : 2, "age" : 3 }
{ "_id" : 4, "name" : "c", "sex" : 2, "age" : 4 }
{ "_id" : 5, "name" : "d", "sex" : 2, "age" : 5 }
> db.c1.find().sort({age:1})
{ "_id" : 1, "name" : "a", "sex" : 1, "age" : 1 }
{ "_id" : 2, "name" : "a", "sex" : 1, "age" : 2 }
{ "_id" : 3, "name" : "b", "sex" : 2, "age" : 3 }
{ "_id" : 4, "name" : "c", "sex" : 2, "age" : 4 }
{ "_id" : 5, "name" : "d", "sex" : 2, "age" : 5 }
> db.c1.find().sort({age:-1})
{ "_id" : 5, "name" : "d", "sex" : 2, "age" : 5 }
{ "_id" : 4, "name" : "c", "sex" : 2, "age" : 4 }
{ "_id" : 3, "name" : "b", "sex" : 2, "age" : 3 }
{ "_id" : 2, "name" : "a", "sex" : 1, "age" : 2 }
{ "_id" : 1, "name" : "a", "sex" : 1, "age" : 1 }
>

Limit和Skip方法

  • 语法: db.集合名.find().sort().skip(数字).limit()

  • 说明: skip跳过指定数量(可选),limit限制查询的数量

  • 练习:1-降序查询查询2条,2-降序跳过2条并查询2条

    1
    2
    3
    4
    5
    6
    7
    > db.c1.find().sort({age:-1}).skip(0).limit(2)
    { "_id" : 5, "name" : "d", "sex" : 2, "age" : 5 }
    { "_id" : 4, "name" : "c", "sex" : 2, "age" : 4 }
    > db.c1.find().sort({age:-1}).skip(2).limit(2)
    { "_id" : 3, "name" : "b", "sex" : 2, "age" : 3 }
    { "_id" : 2, "name" : "a", "sex" : 1, "age" : 2 }
    >

实战分页

需求:数据库1 -10数据,每页显示两条(5页)
语法: db.集合名.find().skip().limit(2)

1
2
3
4
5
6
7
8
skip计算公式: (当前页 – 1) * 每页显示条数


1页 1 2 0
2页 3 4 2
3页 5 6 4
4页 7 8 6
5页 9 10 8

小总结

db.集合名.find()
.sort({列:1/-1}) 排序
.skip(数字) 跳过指定数量
.limit(数字) 限制查询条数
.count() 统计总数量

聚合查询

明确需求

思考:如何统计数据、如何实现分组统计等?
回答: 通过MongoDB聚合查询

概念

聚合查询
顾名思义就是把数据聚起来,然后统计

语法

语法

1
2
3
4
db.集合名称.aggregate([
{管道:{表达式}}
...
])

常用管道

1
2
3
4
5
6
$group 将集合中的文档分组,用于统计结果
$match 过滤数据,只要输出符合条件的文档
$sort 聚合数据进一步排序
$skip 跳过指定文档数
$limit 限制集合数据返回文档数
...

常用表达式

1
2
3
4
$sum 总和	$sum:1同count表示统计
$avg 平均
$min 最小值
$max 最大值

准备

1
2
3
4
5
6
use test4
db.c1.insert({_id:1,name:"a" ,sex:1,age:1})
db.c1.insert({_id:2,name:"a" ,sex:1,age:23})
db.c1.insert({_id:3,name:"b",sex:2,age:3})
db.c1.insert({_id:4,name:"c",sex:2,age:4})
db.c1.insert({_id:5,name:"d",sex:2,age:5})

练习

  • 统计男生、女生总年龄

    1
    2
    3
    4
    5
    6
    7
    8
    db.c1.aggregate([
    {
    $group: {
    _id: "$sex",
    rs: {$sum:"$age"}
    }
    }
    ])

    示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    > db.c1.aggregate([
    ... {
    ... $group: {
    ... _id: "$sex",
    ... rs: {$sum:"$age"}
    ... }
    ... }
    ... ])
    { "_id" : 2, "rs" : 12 }
    { "_id" : 1, "rs" : 24 }
    >
  • 统计男生、女生总人数

    1
    2
    3
    4
    5
    6
    7
    8
    db.c1.aggregate([
    {
    $group: {
    _id: "$sex",
    rs: {$sum:1}
    }
    }
    ])

    示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    > db.c1.aggregate([
    ... {
    ... $group: {
    ... _id: "$sex",
    ... rs: {$sum:1}
    ... }
    ... }
    ... ])
    { "_id" : 2, "rs" : 3 }
    { "_id" : 1, "rs" : 2 }
    >
  • 求学生总数和平均年龄

    1
    2
    3
    4
    5
    6
    7
    8
    9
    db.c1.aggregate([
    {
    $group:{
    _id:null,
    total_num:{$sum:1},
    total_avg:{$avg:"$age"}
    }
    }
    ])

    示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    > db.c1.aggregate([
    ... {
    ... $group:{
    ... _id:null,
    ... total_num:{$sum:1},
    ... total_avg:{$avg:"$age"}
    ... }
    ... }
    ... ])
    { "_id" : null, "total_num" : 5, "total_avg" : 7.2 }
  • 查询男生、女生人数、按人数升序

    1
    2
    3
    4
    db.c1.aggregate([
    { $group: {_id:"$sex",rs:{$sum: 1}}},
    { $sort:{rs:1} }
    ])

    示例:

    1
    2
    3
    4
    5
    6
    7
    > db.c1.aggregate([
    ... { $group: {_id:"$sex",rs:{$sum: 1}}},
    ... { $sort:{rs:1} }
    ... ])
    { "_id" : 1, "rs" : 2 }
    { "_id" : 2, "rs" : 3 }
    >

优化索引

生活中的索引

公交路牌、字典的索引、办公区域索引

数据库中的索引

  • 说明:索引是一种排序好的便于快速查询的数据结构
  • 作用:帮助数据库高校的查询数据

索引优缺点

  • 优点

    提高数据查询的效率,降低数据库的IO成本
    通过索引对数据进行排序,降低数据排序的成本,降低CPU的消耗

  • 缺点

占用磁盘空间
大量索引影响SQL语句效率,因为每次插入和修改数据都需要更新索引

语法

  • 创建索引语法: db.集合名.createlndex(待创建索引的列[,额外选项])

  • 参数:

    待创建索引的列:{键:1,….键:-1}
    说明:1升序-1降序 例如{age:1}表示创建age索引并按照升序的方式存储
    额外选项: 设置索引的名称或者唯一索引等等

  • 删除索引语法:

    全部删除: db.集合名.droplndexes()
    删除指定: db.集合名.droplndex(索引名)

  • 查看索引语法: db.集合名.getlndexes()

练习

准备∶向数据库中新增十万条数据

1
2
3
4
5
6
//选择数据库
use test5;
//向数据库中添加数据
for(var i=0;i<100000;i++){
db.c1.insert({'name':"aaa"+i,"age":i});
}

创建普通索引:

需求: 给name添加普通索引

练习1: 给name添加普通索引,命令: db.c1.createIndex({name:1})

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
> db.c1.count()
100000
> db.c1.createIndex({name:1})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
> db.c1.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_"
},
{
"v" : 2,
"key" : {
"name" : 1
},
"name" : "name_1"
}
]
>

练习2: 删除name索引,命令: db.c1.dropIndex('name_1')

1
2
3
4
5
> db.c1.dropIndex('name_1')
{ "nIndexesWas" : 2, "ok" : 1 }
> db.c1.getIndexes()
[ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_" } ]
>

练习3: 给name创建索引并起名zykj

命令: db.c1.createIndex({name:1},{name:"zykj"})

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
> db.c1.createIndex({name:1},{name:"zykj"})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
> db.c1.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_"
},
{
"v" : 2,
"key" : {
"name" : 1
},
"name" : "zykj"
}
]
>

创建符合索引

需求:给name和age添加组合索引

说明:就是一次给两个字段建立索引

语法:db.集合名.createIndex({键1:方式,键2:方式})

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
> db.c1.createIndex({name:1,age:1})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 2,
"numIndexesAfter" : 3,
"ok" : 1
}
> db.c1.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_"
},
{
"v" : 2,
"key" : {
"name" : 1
},
"name" : "zykj"
},
{
"v" : 2,
"key" : {
"name" : 1,
"age" : 1
},
"name" : "name_1_age_1"
}
]
>

创建唯一索引

需求:给 name 添加普通索引

语法:db.集合名.createIndex(待添加索引的列,{unique:列名})

练习1:删除全部索引,命令: db.c1.dropIndexes()

1
2
3
4
5
6
7
8
9
> db.c1.dropIndexes()
{
"nIndexesWas" : 3,
"msg" : "non-_id indexes dropped for collection",
"ok" : 1
}
> db.c1.getIndexes()
[ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_" } ]
>

练习2:设置唯一索引、命令:db.createIndex({name:1},{unique:"name"})

1
2
3
4
5
6
7
8
> db.c1.createIndex({name:1},{unique:"name"})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
>

练习3:测试唯一索引的特性,

命令: db.c1.insert({name:"a"}) db.c1.insert({name:"a"})

1
2
3
4
5
6
7
8
9
10
11
12
> db.c1.insert({name:"a"})
WriteResult({ "nInserted" : 1 })
> db.c1.insert({name:"a"})
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" : "E11000 duplicate key error collection: test5.c1 index: name_1 dup key: { name: \"a\" }"
}
})
>

分析索引(explain)

语法: db.集合名.find().explain('executionStats')
说明:

  • COLLSCAN全表扫描
  • IXSCAN索引扫描
  • FETCH 根据索引去检索指定document

练习

测试: age未添加索引情况
语法: db.c1.find({age:18}).explain('executionStats');

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
> db.c1.find({age:18}).explain('executionStats')
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test5.c1",
"indexFilterSet" : false,
"parsedQuery" : {
"age" : {
"$eq" : 18
}
},
"winningPlan" : {
"stage" : "COLLSCAN",
"filter" : {
"age" : {
"$eq" : 18
}
},
"direction" : "forward"
},
"rejectedPlans" : [ ]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1,
"executionTimeMillis" : 121,
"totalKeysExamined" : 0,
"totalDocsExamined" : 100001,
"executionStages" : {
"stage" : "COLLSCAN",
"filter" : {
"age" : {
"$eq" : 18
}
},
"nReturned" : 1,
"executionTimeMillisEstimate" : 7,
"works" : 100003,
"advanced" : 1,
"needTime" : 100001,
"needYield" : 0,
"saveState" : 100,
"restoreState" : 100,
"isEOF" : 1,
"direction" : "forward",
"docsExamined" : 100001
}
},
"serverInfo" : {
"host" : "MACHENIKE-SRTYLP00",
"port" : 27017,
"version" : "4.4.0",
"gitVersion" : "563487e100c4215e2dce98d0af2a6a5a2d67c5cf"
},
"ok" : 1
}
>

测试:age 未添加索引情况
语法:db.c1.find({age:18}).explain ('executionStats');

测试:age 添加索引情况
语法:db.c1.createIndex ({age: 1})
继续:db.c1.find({age:18}).explain('executionStats')

选择规则(如何选择合适的列创建索引)

  • 为常做条件、排序、分组、联合操作的字段建立索引
  • 选择唯—性索引(ps.同值较少如性别字段)
  • 选择较小的数据列,为较长的字符串使用前缀索引(ps.索引文件更小)

权限机制

明确需求

发现我们再DOS窗口直接输入命令就可以登录数据库

这在实战工作中绝对不允许的

思考:如何解决

回答: 使用权限机制,开启验证模式即可

语法

1
2
3
4
5
6
7
8
db.createUser({ 
"user" : "账号",
"pwd": "密码",
"roles" : [{
role: "角色",
db: "所属数据库"
}]
})
角色种类说明
超级用户角色root
数据库用户角色readreadWrite
数据库管理角色dbAdminuserAdmin
集群管理角色clusterAdminclusterManagerclusterMonitorhostManager
备份恢复角色backuprestore
所有数据库角色readAnyDatabasereadWriteAnyDatabaseuserAdminAnyDatabasedbAdminAnyDatabase
角色角色说明
root只在 admin 数据库中可用。超级账号,超级权限;
read允许用户读取指定数据库
readWrite允许用户读写指定数据库
dbAdmin允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问 system.profile;
dbAdminAnyDatabase只在 admin 数据库中可用,赋予用户所有数据库的 dbAdmin 权限
clusterAdmin只在 admin 数据库中可用,赋予用户所有分片和复制集相关函数的管理权限
userAdmin允许用户向 system.users 集合写入,可以找指定数据库里创建、删除和管理用户
userAdminAnyDatabase只在 admin 数据库中可用,赋予用户所有数据库的 userAdmin 权限
readAnyDatabase只在 admin 数据库中可用,赋予用户所有数据库的读权限
readWriteAnyDatabase只在 admin 数据库中可用,赋予用户所有数据库的读写权限

开启验证模式

开启验证模式概念: 名词,指用户需要输入账号密码才能登陆使用
操作步骤

  1. 添加超级管理员
  2. 退出卸载服务
  3. 重新安装需要输入账号密码的服务(注在原安装命令基础上加上–auth即可
  4. 启动服务->登陆测试

步骤1∶添加超级管理员

1
2
3
4
5
6
7
8
9
10
mongo
use admin
db.createUser({
"user": "admin",
"pwd": "123456",
"roles": [{
role: "root",
db: "admin"
}]
})

脚下留心:2.x3.x4.x前面版本默认是看不到admin没关系你直接选中即可

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
> db.createUser({
... "user": "admin",
... "pwd": "123456",
... "roles": [{
... role: "root",
... db: "admin"
... }]
... })
Successfully added user: {
"user" : "admin",
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
}
> show collections
system.users
system.version
> db.system.users.find().pretty()
{
"_id" : "admin.admin",
"userId" : UUID("3f00e53b-8c36-4c75-adc3-6c0b78449490"),
"user" : "admin",
"db" : "admin",
"credentials" : {
"SCRAM-SHA-1" : {
"iterationCount" : 10000,
"salt" : "K8myxTY/yJz7RvZiQWqg/w==",
"storedKey" : "oF2VefhQw26ViWm4GTdKTFcgTTM=",
"serverKey" : "G3AZip1W1v35PXvyGqlBDSocy0I="
},
"SCRAM-SHA-256" : {
"iterationCount" : 15000,
"salt" : "pVUDZjB183V6DeDnVQZ3Dy1fmGbedWQedDLCLA==",
"storedKey" : "wRwieyrn5ZT8TnEzqcqHEGUA2/n6TrPNlcNaAtibO9E=",
"serverKey" : "bJIbWRbis72kyw/WF48F9m58kpHK8rcVZbQL6kehoPQ="
}
},
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
}
>

步骤2: 退出卸载服务

脚下留心: DOS窗口必须用管理员省份运行

1
bin\mongod --remove

示例:

1
2
3
4
5
6
7
8
9
10
D:\Programs\MongoDB\bin>mongod --remove
{"t":{"$date":"2020-08-22T21:42:20.619+08:00"},"s":"I", "c":"CONTROL", "id":23285, "ctx":"main","msg":"Automatically disabling TLS 1.0, to force-enable TLS 1.0 specify --sslDisabledProtocols 'none'"}
{"t":{"$date":"2020-08-22T21:42:20.623+08:00"},"s":"W", "c":"ASIO", "id":22601, "ctx":"main","msg":"No TransportLayer configured during NetworkInterface startup"}
{"t":{"$date":"2020-08-22T21:42:20.625+08:00"},"s":"I", "c":"NETWORK", "id":4648602, "ctx":"main","msg":"Implicit TCP FastOpen in use."}
{"t":{"$date":"2020-08-22T21:42:20.625+08:00"},"s":"I", "c":"CONTROL", "id":23307, "ctx":"main","msg":"Trying to remove Windows service '{toUtf8String_serviceName}'","attr":{"toUtf8String_serviceName":"MongoDB"}}
{"t":{"$date":"2020-08-22T21:42:20.647+08:00"},"s":"I", "c":"CONTROL", "id":23310, "ctx":"main","msg":"Service {toUtf8String_serviceName} is curnettly running, stopping service","attr":{"toUtf8String_serviceName":"MongoDB"}}
{"t":{"$date":"2020-08-22T21:42:20.647+08:00"},"s":"I", "c":"CONTROL", "id":23311, "ctx":"main","msg":"Service '{toUtf8String_serviceName}' stopped","attr":{"toUtf8String_serviceName":"MongoDB"}}
{"t":{"$date":"2020-08-22T21:42:20.649+08:00"},"s":"I", "c":"CONTROL", "id":23312, "ctx":"main","msg":"Service '{toUtf8String_serviceName}' removed","attr":{"toUtf8String_serviceName":"MongoDB"}}

D:\Programs\MongoDB\bin>

步骤3∶安装需要身份验证的MongoDB服务

在原安装命令基础上加 --auth

1
mongod --install --dbpath ‪D:\Programs\MongoDB\data --logpath ‪D:\Programs\MongoDB\logs\mongoDB2.log --auth

示例:

1
2
3
4
5
6
7
D:\Programs\MongoDB\bin>mongod --install --dbpath D:\Programs\MongoDB\data --logpath D:\Programs\MongoDB\logs\mongoDB2.log --auth
D:\Programs\MongoDB\bin>net start mongodb
MongoDB 服务正在启动 ..
MongoDB 服务已经启动成功。


D:\Programs\MongoDB\bin>

通过超级管理员账号登录

  • 方法1: mongo服务器IP地址:端口/数据库 -u 用户名 -p 密码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    D:\Programs\MongoDB\bin>mongo localhost:270107/admin -u admin -p 123456
    MongoDB shell version v4.4.0
    exception: Port number 270107 out of range parsing HostAndPort from "localhost:270107"
    exiting with code 1

    D:\Programs\MongoDB\bin>mongo localhost:27017/admin -u admin -p 123456
    MongoDB shell version v4.4.0
    connecting to: mongodb://localhost:27017/admin?compressors=disabled&gssapiServiceName=mongodb
    Implicit session: session { "id" : UUID("05f0c834-a11b-42e7-af35-eafddd17cf95") }
    MongoDB server version: 4.4.0
    ---
    The server generated these startup warnings when booting:
    2020-08-22T21:56:41.558+08:00: This server is bound to localhost. Remote systems will be unable to connect to this server. Start the server with --bind_ip <address> to specify which IP addresses it should serve responses from, or with --bind_ip_all to bind to all interfaces. If this behavior is desired, start the server with --bind_ip 127.0.0.1 to disable this warning
    ---
    ---
    Enable MongoDB's free cloud-based monitoring service, which will then receive and display
    metrics about your deployment (disk utilization, CPU, operation statistics, etc).

    The monitoring data will be available on a MongoDB website with a unique URL accessible to you
    and anyone you share the URL with. MongoDB may use this information to make product
    improvements and to suggest MongoDB products and deployment options to you.

    To enable free monitoring, run the following command: db.enableFreeMonitoring()
    To permanently disable this reminder, run the following command: db.disableFreeMonitoring()
    ---
    >
  • 方法2: a-先登录,b-选择数据库,c-输入db.auth(用户名,密码)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    D:\Programs\MongoDB\bin>mongo
    MongoDB shell version v4.4.0
    connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
    Implicit session: session { "id" : UUID("a3cc854e-96aa-445e-9824-5514ef382981") }
    MongoDB server version: 4.4.0
    > use admin
    switched to db admin
    > db.auth('admin','123456')
    1
    > show dbs
    admin 0.000GB
    config 0.000GB
    local 0.000GB
    school 0.000GB
    test2 0.000GB
    test3 0.000GB
    test4 0.000GB
    test5 0.004GB
    >

练习

  • 需求

    添加用户shop1可以读shop数据库
    添加用户shop2可以读写shop数据库
    脚下留心: 必须在对应数据库创建用户

  • 准备: 创建测试数据和测试用户(注:选择shop仓库创建用户)

    1
    2
    3
    4
    use shop;
    for(var i=1; i<=10; i++) {
    db.goods .insert({ "name" : "goodsName"+i , "price" :i});
    }
  • 添加用户并设置权限

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // 切记
    use shop

    // shop1 只能读
    db.createUser({
    "user" : "shop1",
    "pwd": "shop1",
    "roles" : [{
    role: "read",
    db: "shop"
    }]
    })

    // shop2 只能写
    db.createUser({
    "user" : "shop2",
    "pwd": "shop2",
    "roles" : [{
    role: "readWrite",
    db: "shop"
    }]
    })
  • 验证

    1
    2
    3
    mongo localhost:270107/shop -u shop1 -p shop1

    mongo localhost:270107/shop -u shop2 -p shop2

备份还原

明确需求

在实战工作中一定要做好数据库备份工作
否则万一数据丢失
带来的影响是巨大的

不知道为啥下面的命令我执行不了。。。

备份数据库mongodump

1
mongodump -h -port -u -p -d -o
  • -h 表示服务器 IP 地址(不写默认本机)
  • -port 表示端口(默认 27017)
  • -u 表示账号
  • -p 表示密码
  • -d 表示数据库(数据库不写则导出全部)
  • -o 备份到指定目录下

  • 练习(备份所有数据): mongodump -u admin -p 123456 -o ‪D:\Programs\MongoDB\bak

  • 练习(备份指定数据): mongodump -u shop2 -p shop2 -d shop -o ‪D:\Programs\MongoDB\bak

还原数据库mongorestore

1
mongorestore -h -port -u -p --drop -d
  • -h 表示服务器 IP 地址(不写默认本机)
  • -port 表示端口(默认 27017)
  • -u 表示账号
  • -p 表示密码
  • -d 表示数据库(数据库不写则还原所有)
  • –drop 表示先删除在导出,不写则覆盖
  1. 还原所有数据

    1
    mongorestore -u admin -p 123456 --drop D:\Programs\MongoDB\back
  2. 备份指定数据库

    1
    mongorestore -u shop2 -p shop2 -d shop --drop D:\Programs\MongoDB\back1\shop

实战可视化管理工具

简介

adminMongo WEB/PC端口网页管理 https://adminmongo.markmoffat.com/
Robo 3T * 客户端软件 https://robomongo.org/download/
MongoVUE 客户端软件

Navicat 客户端软件 (同样推荐使用)

安装Robo 3T

安装步骤省略