0%

从零开始的 MongoDB 学习生活

写在前面

教程来自 w3school菜鸟教程

本文仅作个人的学习笔记

#01 Get Started

MongoDB 是一个文档型数据库。与 SQL 不同,它是非关系型数据库。

MongoDB 可以把数据存在一起而不是分成多个表,因此它有着很快的读取速度。

在 MongoDB 里也可以把数据分为多个组,它们被叫做 collections(集合) 而不是 tables(表)

这里使用的是 mongosh 来连接数据库。

1
mongosh "mongodb+srv://cluster0.anmcend.mongodb.net/myFirstDatabase" --apiVersion 1 --username deffield62

连接成功后会得到以下信息

1
2
3
4
5
6
7
8
9
10
PS C:\Users\Administrator> mongosh "mongodb+srv://cluster0.anmcend.mongodb.net/myFirstDatabase" --apiVersion 1 --username deffield62
Enter password: ****************
Current Mongosh Log ID: 642d2c3883d22d14fd1241fd
Connecting to: mongodb+srv://<credentials>@cluster0.anmcend.mongodb.net/myFirstDatabase?appName=mongosh+1.8.0
Using MongoDB: 5.0.15 (API Version 1)
Using Mongosh: 1.8.0

For mongosh info see: https://docs.mongodb.com/mongodb-shell/

Atlas atlas-63kw15-shard-0 [primary] myFirstDatabase>

报错处理

  • Error: queryTxt ETIMEOUT cluster0.anmcend.mongodb.net

    MongoServerSelectionError: connection to 23.101.10.160:27017 closed

    SECURITY 下的 Network Access 里面添加 0.0.0.0/0 即可(即不校验连接时的 IP)

#02 创建数据库 / 集合

输入 db 以查看目前在使用哪个数据库

1
2
> db
myFirstDatabase

创建一个数据库

使用 use DatabaseName

如果数据库不存在,则创建数据库。然后切换到指定数据库。

1
2
> use blog
switched to db blog

创建一个集合

使用 db.createCollection(name[, options])

name 是创建的集合名称

options 指定有关内存大小及索引的选项

字段 类型 描述
capped 布尔 如果为 true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。
当该值为 true 时,必须指定 size 参数。
size 数值 为固定集合指定一个最大值,即字节数。
如果 capped 为 true,也需要指定该字段。
max 数值 指定固定集合中包含文档的最大数量。
1
2
3
4
> db.createCollection("posts")
{ ok: 1 }
> db.createCollection("articles", {capped: true, size: 6142800, max: 10000})
{ ok: 1 }

创建了一个集合 posts

创建了一个固定集合 articles ,整个集合空间大小 6142800 B, 文档最大个数为 10000 个。

展示所有的数据库 / 集合

使用 show dbs 展示所有数据库

1
2
3
4
> show dbs
blog 16.00 KiB
admin 336.00 KiB
local 5.42 GiB

空数据库不会在这里被列出来,因为空数据库实际上是不存在的

仅当被写入数据时,一个数据库才被实际地创建

使用 show collections 展示当前数据库里面的所有集合

1
2
3
> show collections
articles
posts

删除数据库 / 集合

使用 db.collectionName.drop() 以删除名为 collectionName 的集合

1
2
3
4
5
6
7
> show collections
collection01
collection02
> db.collection01.drop()
true
> show collections
collection02

使用 db.dropDatabase() 以删除当前数据库。

1
2
3
4
5
6
7
8
9
10
11
> show dbs
blog 16.00 KiB
test 16.00 KiB
admin 336.00 KiB
local 5.42 GiB
> db.dropDatabase()
{ ok: 1, dropped: 'test' }
> show dbs
blog 16.00 KiB
admin 336.00 KiB
local 5.42 GiB

报错处理

  • MongoServerError: user is not allowed to do action [dropDatabase] on [test.]

    如果是用的 Altas,需要去 SECURITY - Database Access 添加权限

    Database User Privileges 里将 Built-in Role 设置为 Altas admin

#03 增查删改

使用 db.collectionName.insertOne(document) 插入单个文档。

document 是 BSON(一种类似 JSON 的二进制形式的存储格式,是 Binary JSON 的简称)格式。

1
2
3
4
5
6
7
8
9
10
11
12
13
> db.posts.insertOne({
... title: "Post Title 1",
... body: "Body of post.",
... category: "News",
... likes: 1,
... tags: ["news", "events"],
... date: Date()
... })

{
acknowledged: true,
insertedId: ObjectId("642d3c23a54ba5b8b7555bc7")
}

使用 db.collectionName.insertMany(documents) 插入多个文档。

documents 是由 document 组成的列表。

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
> db.posts.insertMany([
... {
... title: "Post Title 2",
... body: "Body of post.",
... category: "Event",
... likes: 2,
... tags: ["news", "events"],
... date: Date()
... },
... {
... title: "Post Title 3",
... body: "Body of post.",
... category: "Technology",
... likes: 3,
... tags: ["news", "events"],
... date: Date()
... },
... {
... title: "Post Title 4",
... body: "Body of post.",
... category: "Event",
... likes: 4,
... tags: ["news", "events"],
... date: Date()
... }
... ])

{
acknowledged: true,
insertedIds: {
'0': ObjectId("642d3ce6a54ba5b8b7555bc9"),
'1': ObjectId("642d3ce6a54ba5b8b7555bca"),
'2': ObjectId("642d3ce6a54ba5b8b7555bcb")
}
}

如果 collectionName 不存在,会自动创建这个集合。

使用 db.collectionName.find([query, projection]) 来查询满足 query所有文档。

可使用 projection 以选择性地展示查询结果

在同一个 projection 中除了 _id 字段不能同时出现 0 和 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
> db.posts.find({},{title: 1, body: 1, date: 1, _id: 0, likes: 1})
[
{
title: 'Post Title 2',
body: 'Body of post.',
likes: 2,
date: 'Wed Apr 05 2023 18:11:46 GMT+0800 (中国标准时间)'
},
{
title: 'Post Title 13',
body: 'Body of post.',
likes: 2,
date: 'Wed Apr 05 2023 18:11:58 GMT+0800 (中国标准时间)'
},
{
title: 'Post Title 18',
body: 'Body of post.',
likes: 5
}
]

使用 db.collectionName.findOne([query,projection]) 以查找满足条件的第一个文档

1
2
3
4
5
6
7
8
9
10
> db.posts.findOne({likes: 2})
{
_id: ObjectId("642d4962a54ba5b8b7555bd0"),
title: 'Post Title 2',
body: 'Body of post.',
category: 'Event',
likes: 2,
tags: [ 'news', 'events' ],
date: 'Wed Apr 05 2023 18:11:46 GMT+0800 (中国标准时间)'
}

查询操作符

  • 比较

    在查询操作符中,一般来说,e 表示 equalg 表示 greaterl 表示 lesst 表示 thann 表示 not

    所以 $eq$ne$gt$gte$lt$lte$in 分别表示:等于、不等于、大于、大于等于、小于、小于等于、属于

  • 逻辑

    $and$or$not 分别表示二者都、二者任一、二者都不(含不包含该字段的文档)

    $nor 表示二者都不

  • 求值

    $regex 使用正则表达式匹配

    $text 执行文本搜索

    $where 使用 JS 表达式以匹配文档

更多操作符详见 官方文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# likes > 2 || title == "Post Title 2"

> db.posts.find({$or: [{"likes": {$gt: 2}}, {"title": "Post Title 2"}]})
[
{
_id: ObjectId("642d496ea54ba5b8b7555bd3"),
title: 'Post Title 2',
body: 'Body of post.',
category: 'Event',
likes: 2,
tags: [ 'news', 'events' ],
date: 'Wed Apr 05 2023 18:11:58 GMT+0800 (中国标准时间)'
},
{
_id: ObjectId("642d496ea54ba5b8b7555bd5"),
title: 'Post Title 18',
body: 'Body of post.',
category: 'Event',
likes: 5
}
]

使用 db.collectionName.deleteOne(query) 删除第一个满足 query 的文档

1
2
> db.posts.deleteOne({ likes: 5, category: "Event" })
{ acknowledged: true, deletedCount: 1 }

使用 db.collectionName.deleteMany(query) 删除所有满足 query 的文档

1
2
> db.posts.deleteMany({ category: "Technology" })
{ acknowledged: true, deletedCount: 3 }

使用 db.collectionName.updateOne(query, update[, upsert]) 以修改第一个满足 query 的文档

使用 db.collectionName.updateMany(query, update[, upsert]) 以修改所有满足 query 的文档

upsert 表示如果不存在 update 的记录是否新插入一个文档

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
> db.posts.updateOne( { title: "Post Title 2" }, { $set: { likes: 9 } } )
{
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}
>
> db.posts.updateOne(
... { title: "Post Title 5" },
... {
... $set:
... {
... title: "Post Title 5",
... body: "Body of post.",
... category: "Event",
... likes: 5,
... tags: ["news", "events"],
... date: Date()
... }
... },
... { upsert: true }
... )
{
acknowledged: true,
insertedId: ObjectId("642d59c11a7c3a441ae6fac4"),
matchedCount: 0,
modifiedCount: 0,
upsertedCount: 1
}

修改操作符

更多修改操作符详见 官方文档

摘几个看着很有用的

操作符 描述 示例
$set 设置字段对应的值 {$set: {likes: <new value>}}
$inc 增加字段对应的值 {$inc: {likes: -5}}
$min 与原字段值取最小 {$min: {likes: 17}}
$max 与原字段值取最大 {$max: {likes: 17}}
$mul 将原字段乘上某值 {$mul: {likes: 3}}
$rename 修改字段名 {$rename: {"nickname": "alias"}}
$unset 移除字段名 {$unset: {quantity: ""}}