快速入门指南
如何安装
采用docker 安装 MongoDB:
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
version: '3.1'
services:
mongo:
image: mongo
restart: unless-stopped
environment:
TZ: Asia/Shanghai
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: root
ports:
- 27017:27017
logging:
driver: json-file
options:
max-size: "300M"
max-file: "3"
mongo-express:
image: mongo-express
restart: unless-stopped
ports:
- 8081:8081
logging:
driver: json-file
options:
max-size: "300M"
max-file: "3"
environment:
TZ: Asia/Shanghai
ME_CONFIG_MONGODB_ADMINUSERNAME: root
ME_CONFIG_MONGODB_ADMINPASSWORD: root
ME_CONFIG_MONGODB_URL: mongodb://root:root@mongo:27017/
如何连接
使用 navicat 或者 docker 安装的 mongo-express 来连接
mongodb://[username:password@]host1[:port1][,host2[:port2],…[,hostN[:portN]]][/[database][?options]]
快速入门指南
RDBMS & MongoDB
RDBMS | MONGO | 对应关系 |
---|---|---|
database | database | 数据库 |
table | collection | 数据库表/集合 |
row | document | 数据记录行/文档 |
column | field | 数据字段/域 |
index | index | 索引 |
table joins | 表连接,MongoDB不支持 | 内嵌文档 |
primary key | primary key | 主键,MongoDB自动将_id字段设置为主键 |
以上为关系型数据库与 MongoDB 的对比关系(数据结构维度)
数据库操作
MongoDB 的操作维度都是现切换到对应的工作空间(use 数据库), 然后在使用对应的命令对当前工作空间做操作
1
2
3
4
5
6
7
8
9
-- 1. 查看所有数据库
show dbs;
-- 2. 创建/切换数据库
use database;
-- 3. 删除数据库
db.dropDatabase()
集合新增相关操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- 1. 新建集合
db.createCollection(name, { capped: true, autoIndexId: true, size: 6142800, max: 10000 } )
-- capped: 布尔(可选)如果为 true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。当该值为 true 时,必须指定 size 参数。
-- autoIndexId: 布尔 3.2 之后不再支持该参数。(可选)如为 true,自动在 _id 字段创建索引。默认为 false。
-- size: 数值 (可选)为固定集合指定一个最大值,即字节数。如果 capped 为 true,也需要指定该字段。
-- max: 数值 (可选)指定固定集合中包含文档的最大数量。
-- 2. 向数据库对应的集合新增数据(集合不存在则新建)
db.[tablename].insert({"key": "value"})
db.[tablename].insertOne({"key": "value"})
db.[tablename].insertMany([{"key1": "value1"}, {"key2": "value2"}])
-- insert 与 insertOne的区别在于 后者返回插入后的 ID 以及 ack 标志
集合修改文档操作
语法:
1
2
3
4
5
6
7
8
9
db.collection.update(
<query>, update的查询条件,类似sql update查询内where后面的。
<update>, update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的
{
upsert: <false>, 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
multi: <false>, 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
writeConcern: <document> 可选,抛出异常的级别。
}
)
1
2
3
4
-- 1. 更新 demo2 集合, 查找 kkk=0 的项, 修改 aaa 列为 232, 如果没有 aaa 列, 就新增, 该操作是批量操作({"multi": true})
db.demo2.update({"kkk":0}, {$set: {"aaa": 232}}, {"multi": true})
-- 等效于
db.demo2.update({"kkk":0}, {$set: {"aaa": 232}}, false, true)
集合删除文档操作
语法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
db.collection.remove(
<query>, (可选)删除的文档的条件。
{
justOne: <boolean>, (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
writeConcern: <document> (可选)抛出异常的级别。
}
)
db.collection.deleteOne(
<query>
)
db.collection.deleteMany(
<query>
)
1
2
3
4
-- 1. 删除 demo2 集合 kkk=0 的数据集, 只删除匹配的第一条
db.demo2.remove({"kkk":0}, true)
-- 等效于
db.demo2.deleteOne({"kkk":0})
集合查询文档操作
通过上述片段, 我们可以发现一些规律: MongoDB 入参, 都是 json 类型数据, 动作&条件 等使用 $.. 这些关键字来代替, 比如: $set
下面通过查询的例子, 更加可以看到其中的规律
语法:
1
2
3
4
db.collection.find(
<query>,
<projection> 可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。
)[.pretty()]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-- 1. 查询 demo2 中 aaa=232, kkk 大于或等于0, 并且 kkk 等于 0 或 2, 并且只过滤出 aaa 列存储的类型是 doubule 的数据
-- limit(2): 只查 2 条
-- skip(1): 略过前 1 条数据
-- .sort({"kkk":1}): 按照 aaa 字段升序排列 (-1 是降序)
db.demo2.find({
"aaa": 232,
"aaa": {$type: 'double'},
$or: [{"kkk": 0}, {"kkk": 2}],
"kkk": {$gte: 0}
}).skip(1).limit(2).sort({"aaa":1}).pretty()
-- 模糊查询 123, 只召回 deviceCode, 其他字段不要, 但是默认 _id 也会召回
res = db.device_gps.find({deviceCode: /123/}, { 'deviceCode': 1 }).limit(10)
while (res.hasNext()) {
x = res.next()
print(x.deviceCode + "\n")
}
find函数接收的查询数组, 都是 and 操作, 如果想加入 or, 那么就加一个 or 的属性, 支持比较运算符
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
db.collection.find({ field: { $gt: value } }) -- 大于
db.collection.find({ field: { $lt: value } }) -- 小于
db.collection.find({ field: { $ne: value } }) -- 不等于
db.collection.find({ field: { $in: [value1, value2] } }) -- 在指定的值数组中
db.collection.find({
location: {
$geoWithin: {
$centerSphere: [[longitude, latitude], radius / 3963.2] -- 半径以英里为单位
}
}
})
db.collection.find({
location: {
$near: {
$geometry: { type: "Point", coordinates: [longitude, latitude] },
$maxDistance: distance -- 最大距离,单位为米
}
}
})
集合索引操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- 1. demo2创建索引, 用 kkk 列 (升序) -1 是降序
db.demo2.createIndex({"kkk":1}, {"name": "idx_kkk", "unique": false})
-- 2. 查看所有索引
db.demo2.getIndexes()
-- 3. 查看索引大小
db.demo2.totalIndexSize()
-- 4. 删除所有索引
db.demo2.dropIndexes()
-- 5. 删除指定索引
db.col.dropIndex("idx_kkk")
集合聚合操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
db.demo2.aggregate([
{ $match: { field: xxx } },
{
$group: {
_id: "$kkk",
xxx: {$sum: "$aaa"},
ccc: {$avg: "$aaa"},
zzz: {$min: "$aaa"},
vvv: {$max: "$aaa"},
bbb: {$push: "$aaa"},
ttt: {$first: "$aaa"},
qqq: {$last: "$aaa"},
rrr: {$addToSet: "$aaa"},
}
},
{
$project: {
_id: 1,
xxx: 1
}
}
])
最终输出的结果只有 _id 和 xxx, 因为被 project 管道过滤了
MongoDB 集合函数接收为管道函数, 支持经过的管道如下:
1
2
3
4
5
6
7
8
9
10
11
$project : 修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
$match : 用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。
$limit : 用来限制MongoDB聚合管道返回的文档数。
$skip : 在聚合管道中跳过指定数量的文档,并返回余下的文档。
$unwind : 将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
$group : 将集合中的文档分组,可用于统计结果。
$sort : 将输入文档排序后输出。
$geoNear : 输出接近某一地理位置的有序文档。
$out : 把管道的结果写入某个集合。
$redact : 控制特定数据的访问。
$lookup : 多表关联
$lookup 管道函数示例:
1
2
3
4
5
6
7
8
9
10
11
db.产品.aggregate([
{
$lookup:
{
from: "库存",
localField: "产品item",
foreignField: "库存sku",
as: "inventory_docs"
}
}
])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"_id" : NumberInt("1"),
"item" : "almonds",
"price" : NumberInt("12"),
"quantity" : NumberInt("2"),
"inventory_docs" : [
{
"_id" : NumberInt("1"),
"sku" : "almonds",
"description" : "product 1",
"instock" : NumberInt("120")
}
]
}