MongoDB 入门

MongoDB 入门

数据库

shell
1
2
3
4
5
6
7
8
9
10
11
12
13
# 查询所有数据库
show databases; | show dsb;

# 创建/切换到指定的数据库。如果数据库不存在任何集合,使用 `show dbs` 将不会展示该数据库
use [database];
# 创建(如果不存在)/切换到 test 数据库
use test;

# 查询当前所在的数据库
db

# 删除当前数据库
db.dropDatabase();

集合

shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 查询数据库中的所有集合
show collections; | show tables;

# 显式创建集合
db.createCollection("[集合名称]");
# 创建一个集合名称为 user 的集合
db.createCollection("user");
# 通过新增一条文档记录,隐式创建一个集合。比如:往 user 集合中插入一条 name 为 wuhunyu 的文档,将会隐式地创建 user 集合
db.user.insert({name: "wuhunyu"});

# 删除一个集合
db.[集合].drop();
# 删除一个名称为 user 的集合
db.user.drop();

文档

插入

shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 单行插入
db.[集合名称].insert([文档])
# 往 user 集合中插入一条 name 为 wuhunyu 的文档
db.user.insert({name: "wuhunyu"});

# 批量插入
db.[集合名称].insertMany([文档1, 文档2...]);
# 批量插入
db.user.insertMany([{_id: 1, name: "1号"}, {name: "2号", age: 25}, {name: "3号", bir: "2023-12-16"}]);
# 使用 insert 也可以批量插入
db.user.insert([{_id: 1, name: "1号"}, {name: "2号", age: 25}, {name: "3号", bir: "2023-12-16"}]);

# js 脚本插入
for (let i = 0; i < 10; i++) {
db.user.insert({_id: i, name: i + "号", age: i + 20});
}

删除

shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 删除集合全部的文档记录
db.[集合].remove({});
# 删除 user 集合中的全部数据
db.user.remove({});
# 删除 user 集合中的 _id 为 1 的文档记录
db.user.remove({_id: 1});
# 如果是 mongo 自动生成的 id,需要使用 ObjectId("[id]") 的方式指定 _id
db.user.remove({_id: ObjectId("657d08e9cb5c0571e33ee6b4")});
# 删除 user 集合中的 name 为 "1号" 的文档记录
db.user.remove({name: "1号"});

# 删除一条记录
db.[集合].remove({}, {justOne: true});
# 删除 user 集合中 age 字段为 20 的第一条记录
db.user.remove({age: 20}, {justOne: true});

修改

shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 修改
# 查询条件 可以类比成 where 条件
# 修改值 可以类比成 set
# multi 表示是否批量更新,默认为 false,即为只更新找到的第一条记录
# upsert 表示查询条件查询不存在记录时,是否新增,默认为 false
db.[集合].update(
{[查询条件]},
{[修改值]},
{
multi: <boolean>,
upsert: <boolean>,
}
);
# 修改 user 集合中第一条 age 为 20 的文档记录。这种修改方式类似于删除之后再新增,修改之后的字段只会保留 _id 和 age 字段
db.user.update({age: 20}, {age: 25});
# 修改 user 集合中第一条 age 为 20 的文档记录。这种修改方式类似于部分修改,只修改指定的字段
db.user.update({age: 20}, {$set: {age: 25}});
# 修改 user 集合中的所有 age 为 20 的文档记录
db.user.update({age: 20}, {$set: {age: 25}}, {multi: true});

查询

shell
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
58
59
60
61
62
63
64
65
66
67
68
# 查询全部
db.[集合].find();
# 查询 user 集合中的全部文档记录
db.user.find();
# 格式化显示,对于较长的文档记录,可以使用 .pretty() 来格式化展示
db.user.find().pretty();

# 操作符
$gt >
$lt <
$gte >=
$lte <=
$ne !=

# 条件查询
db.[集合].find({[查询条件]});
# and 条件查询
# 查询 user 集合中,age 等于 25 的记录
db.user.find({age: 25});
# 查询 user 集合中,age 大于等于 25 的记录
db.user.find({age: {$gte: 25}});
# 查询 user 集合中,age 大于等于 25 且 小于等于 30 的记录
db.user.find({age: {$gte: 25, $lte: 30}});
# 错误写法:后一个 age 条件会覆盖掉前一个查询条件,等价于 `db.user.find({age: 30})`
db.user.find({age: 25, age: 30});

# or 条件查询
# 查询 user 集合中,age 大于等于 25 或者 name 为 "1号" 的记录
db.user.find({$or: [{age: {$gte: 25}}, {name: "1号"}]});

# and 和 or 的联合查询
# 查询 user 集合中,age大于等于 25 或者 name 为 "1号" 且 age 等于 20 的记录
db.user.find({$or: [{age: {$gte: 25}}, {name: "1号", age: 20}]});

# 数组结构。在 mongo 中,数组结构的查询和和普通的查询也是一样的
# 比如,user 集合中一条文档记录有一个字段是 likes
# { "_id" : ObjectId("657d1dfacb5c0571e33ee6c3"), "name" : "test", "likes" : [ "看电视", "看书", "打篮球" ] }
# 如果要查询,likes 中包含了 "看书" 的记录
db.user.find({likes: "看书"});

# 模糊查询。mongo 中并没有像是 `%`, `_` 的标识符,需要通过正则表达式的方式来实现模糊查询
# 查询 user 集合中,name 包含 "号" 的记录
db.user.find({name: /号/}).pretty();

# 排序
db.[集合].find().sort({[排序条件]});
# 1: 升序; -1: 降序
# 查询 user 集合中全部的记录,按 age 倒序,name 顺序 排序
db.user.find().sort({age: -1, name: 1});

# 分页
# skip 偏移量,从 0 开始
# limit 最大条数
db.[集合].find().skip([skip]).limit([limit]);
# 查询 user 集合全部的记录,只保留前 5 条记录,如果 skip 为 0,可以省略 skip,等价于 `db.user.find()limit(5);`
db.user.find().skip(0).limit(5);

# 统计数据量
db.[集合].count();
# 统计 user 集合的中数据量
db.user.count();
# 统计 user 集合中,age 小于等于 25 的记录数量
db.user.find({age: {$lte: 25}}).count();

# 返回指定的字段
db.[集合].find([查询条件], [映射字段]);
# 查询 user 集合中的 name 字段。其中,1 表示显示,0 表示不显示
db.user.find({}, {name: 1});
$type

$type 操作符是基于BSON类型来检索集合中匹配的数据类型,并返回结果

类型 数字 备注
Double 1
String 2
Object 3
Array 4
Binary data 5
Undefined 6 已废弃。
Object id 7
Boolean 8
Date 9
Null 10
Regular Expression 11
JavaScript 13
Symbol 14
JavaScript (with scope) 15
32-bit integer 16
Timestamp 17
64-bit integer 18
Min key 255 Query with -1.
Max key 127
shell
1
2
3
# 查询 user 集合中,name 为字符串类型的文档记录,等价于 `db.user.find({name: {$type: 2}});`
db.user.find({name: {$type: "string"}});
# 值得一提的是,mongo 中的整形的默认类型是 Double

索引

shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 查询集合下的所有索引
db.[集合].getIndexes();
# 查询 user 集合下的所有索引
db.user.getIndexes();

# 创建一个缩影
db.[索引].craeteIndex([索引字段], [索引配置]);
# 创建一个名称为 idx_name_age 的索引,索引字段为 (name, age), 都为升序排列
db.user.createIndex({name: 1, age: 1}, {name: "idx_name_age"});

# 删除集合下的全部索引
db.[集合].dropIndexes();
# 删除 user 集合下的所有索引(除了 id 索引)
db.user.dropIndexes();

# 删除指定索引
db.[集合].dropIndex([索引名称]);
# 删除 user 集合的 idx_name_age 索引
db.user.dropIndex("idx_name_age");

聚合

管道

  • $project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
  • $match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。
  • $limit:用来限制MongoDB聚合管道返回的文档数。
  • $skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。
  • $unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
  • $group:将集合中的文档分组,可用于统计结果。
  • $sort:将输入文档排序后输出。
  • $geoNear:输出接近某一地理位置的有序文档。

聚合函数

表达式 描述
$sum 计算总和。
$avg 计算平均值
$min 获取集合中所有文档对应值得最小值。
$max 获取集合中所有文档对应值得最大值。
$push 将值加入一个数组中,不会判断是否有重复的值。
$addToSet 将值加入一个数组中,会判断是否有重复的值,若相同的值在数组中已经存在了,则不加入。
$first 根据资源文档的排序获取第一个文档数据。
$last 根据资源文档的排序获取最后一个文档数据

测试数据

shell
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
db.mycol.insert([
{
title: 'MongoDB Overview',
description: 'MongoDB is no sql database',
by_user: 'runoob.com',
url: 'http://www.runoob.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 100
},
{
title: 'NoSQL Overview',
description: 'No sql database is very fast',
by_user: 'runoob.com',
url: 'http://www.runoob.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 10
},
{
title: 'Neo4j Overview',
description: 'Neo4j is no sql database',
by_user: 'Neo4j',
url: 'http://www.neo4j.com',
tags: ['neo4j', 'database', 'NoSQL'],
likes: 750
}
]);

示例操作

shell
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# 管道操作
# $project 映射 title 和 by_user 字段
db.mycol.aggregate([
{
$project: {
_id: 0,
title: 1,
by_user: 1
}
}
]);
# $match 过滤 likes >= 100, tags 包含 mongo 的记录
db.mycol.aggregate([
{
$match: {
likes: {
$gte: 100
},
tags: "mongodb"
}
},
{
$project: {
_id: 0,
title: 1,
by_user: 1
}
}
]);
# 分页
db.mycol.aggregate([
{
$match: {
likes: {
$gte: 100
},
tags: "mongodb"
}
},
{
$project: {
_id: 0,
title: 1,
by_user: 1
}
},
{
$skip: 0
},
{
$limit: 10
}
]);
# $unwind 数组拆分
db.mycol.aggregate([
{
$match: {
likes: {
$gte: 100
},
tags: "mongodb"
}
},
{
$unwind: "$tags"
},
{
$project: {
_id: 0,
title: 1,
by_user: 1,
tags: 1
}
},
{
$skip: 0
},
{
$limit: 10
}
]);
# $sort 排序
db.mycol.aggregate([
{
$match: {
likes: {
$gte: 100
},
tags: "mongodb"
}
},
{
$unwind: "$tags"
},
{
$project: {
_id: 0,
title: 1,
by_user: 1,
tags: 1
}
},
{
$sort: {
title: 1,
tags: 1
}
},
{
$skip: 0
},
{
$limit: 10
}
]);
# $group 分组
db.mycol.aggregate([
{
$match: {
likes: {
$gte: 100
},
tags: "database"
}
},
{
$group: {
_id: {
author: "$by_user",
url: "$url"
},
minLikes: {
$min: "$likes"
},
maxLikes: {
$max: "$likes"
},
avgLikes: {
$avg: "$likes"
},
count: {
$sum: 1
},
sum: {
$sum: "$likes"
}
}
}
]).pretty();
作者

wuhunyu

发布于

2023-12-17

更新于

2023-12-17

许可协议