MongoDB基础
开始
MongoDB是一个基于文档的NoSQL数据库
官网:MongoDB
官方文档:MongoDB 文档
MongoDB使用集合(Collections)来组织文档(Documents),每个文档都是由键值对组成的
- 数据库(Database):存储数据的容器,类似于关系型数据库中的数据库
- 集合(Collection):数据库中的一个集合,类似于关系型数据库中的表
- 文档(Document):集合中的一个数据记录,操作最小单位,类似于关系型数据库中的行,以BSON格式存储
相关术语对比
SQL 术语/概念 | MongoDB 术语/概念 | 解释/说明 |
---|---|---|
database | database | 数据库 |
table | collection | 数据库表/集合 |
row | document | 数据记录行/文档 |
column | field | 数据字段/域 |
index | index | 索引 |
table joins | 表连接,MongoDB不支持 | |
primary key | primary key | 主键,MongoDB自动将_id字段设置为主键 |
基本操作
基本命令
show dbs
:查看所有数据库use my_db
:使用数据库,MongoDB中的数据库不需要手动创建,当添加文档时,数据库会自动创建show collections
:查看当前数据库的集合db
:表示当前数据库,使用该对象操作当前数据库db.createCollection("myNewCollection")
:在当前数据库中创建集合,当添加文档时才创建db.myNewCollection.drop()
:删除集合db.dropDatabase()
:删除当前数据库
数据库CRUD
插入文档
插入文档使用以下方法
insertOne()
:插入一个文档,传入一个json格式的对象insertMany()
:插入多个文档,传入一个数组
1
2
3
4
5
6
7
8
9
10
db.myCollection.insertOne({
name: "Alice",
age: 25,
city: "New York"
});
db.myCollection.insertMany([
{ name: "Bob", age: 30, city: "Los Angeles" },
{ name: "Charlie", age: 35, city: "Chicago" }
]);
插入时如果没有指定
_id
字段,则自动创建唯一的_id
作为主键
更新文档
更新文档使用以下方法
updateOne
:更新一个文档updateMany
:更新多个文档replaceOne
:替换一个文档,替换除_id
字段之外的文档的所有内容
updateOne
方法和updateMany
方法传入三个参数,分别是fileter,update,options
- fileter:传入一个json对象,指定要过滤的key,value为一个值或一个表示条件的json对象
- update:传入一个json对象,通过操作符指定更新的行为
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
db.myCollection.updateOne(
{ name: "Alice" }, // 过滤条件
{ $set: { age: 26 } }, // 更新操作,使用set操作符更新值
{ upsert: false } // 可选参数
);
db.myCollection.updateMany(
{ age: { $lt: 30 } }, // 过滤条件,该条件可以匹配多个文档
{ $set: { status: "active" } }, // 更新操作
{ upsert: false } // 可选参数
);
db.myCollection.replaceOne(
{ name: "Bob" }, // 过滤条件
{ name: "Bob", age: 31 } // 新文档的内容
);
删除文档
删除文档使用以下方法
deleteOne
:删除一个文档deleteMany
:删除多个文档
两个方法传入一个fileter参数和一个options参数,filter参数指定过滤条件
1
2
3
db.myCollection.deleteOne({ name: "Alice" });
db.myCollection.deleteMany({ status: "inactive" });
查询文档
查询文档使用以下方法
find
:查询多个文档findOne
:查询一个文档
两个方法传入一个filter参数和projection参数,filter参数指定过滤条件
1
2
3
db.myCollection.find({ age: { $gt: 25 } });
db.myCollection.findOne({ name: "Alice" });
projection参数表示投影,指定返回的字段
1
2
3
4
db.myCollection.find(
{ age: { $gt: 25 } },
{ name: 1, age: 1, _id: 0 } // 返回name和age字段,不返回_id,若不指定_id: 0,则默认返回_id
);
其他查询操作
排序:sort方法
1 2
db.myCollection.find().sort({ age: -1 }); // 按age降序 db.myCollection.find().sort({ age: 1, name: -1 }); // 按age升序,按name降序
跳过:skip方法
1
db.myCollection.find().skip(5); // 跳过前5个文档
限制:limit方法
1
db.myCollection.find().limit(10); // 返回前10个文档
条件操作符
MongoDB中使用一个json对象表示一个条件,条件操作符作为key
比较操作符
比较操作符的value为一个值或一个数组
操作符 | 描述 | 示例 |
---|---|---|
$eq | 等于 | { age: { $eq: 25 } } |
$ne | 不等于 | { age: { $ne: 25 } } |
$gt | 大于 | { age: { $gt: 25 } } |
$gte | 大于等于 | { age: { $gte: 25 } } |
$lt | 小于 | { age: { $lt: 25 } } |
$lte | 小于等于 | { age: { $lte: 25 } } |
$in | 在指定的数组中 | { age: { $in: [25, 30, 35] } } |
$nin | 不在指定的数组中 | { age: { $nin: [25, 30, 35] } } |
逻辑操作符
逻辑操作符的value为一个数组,其中每个元素是一个条件json对象
操作符 | 描述 | 示例 |
---|---|---|
$and | 逻辑与,符合所有条件 | { $and: [ { age: { $gt: 25 } }, { city: "New York" } ] } |
$or | 逻辑或,符合任意条件 | { $or: [ { age: { $lt: 25 } }, { city: "New York" } ] } |
$not | 取反,不符合条件 | { age: { $not: { $gt: 25 } } } |
$nor | 逻辑与非,均不符合条件 | { $nor: [ { age: { $gt: 25 } }, { city: "New York" } ] } |
元素操作符
元素操作符指定元素相关的条件
操作符 | 描述 | 示例 |
---|---|---|
$exists | 字段是否存在 | { age: { $exists: true } } |
$type | 字段的BSON类型 | { age: { $type: "int" } } |
$regex | 字段值匹配正则表达式 | { name: { $regex: /^A/ } } |
数组操作符
操作符 | 描述 | 示例 |
---|---|---|
$all | 数组包含所有指定的元素 | { tags: { $all: ["red", "blue"] } } |
$elemMatch | 数组中的元素匹配指定条件 | { results: { $elemMatch: { score: { $gt: 80 } } } } |
$size | 数组的长度等于指定值 | { tags: { $size: 3 } } |
聚合操作
MongoDB的聚合操作使用aggregate
方法,传入一个数组,数组中的每个对象表示一个聚合管道,每个管道的返回值会作为下一个管道的输入,管道操作符如下
操作符 | 描述 |
---|---|
$project | 修改输入文档的结构,可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档 |
$match | 用于过滤数据,只输出符合条件的文档,使用MongoDB的标准查询操作 |
$limit | 用来限制MongoDB聚合管道返回的文档数 |
$skip | 在聚合管道中跳过指定数量的文档,并返回余下的文档 |
$unwind | 将文档中的某一个数组类型字段拆分成多个文档,每个文档的该字段为数组中的一个值 |
$group | 将集合中的文档分组,可用于统计结果 |
$sort | 将输入文档排序后输出 |
$project
将所有文档投影,不返回_id
需要显示指定
1
2
3
4
5
6
7
8
9
db.article.aggregate([
{
$project : {
_id : 0,
title : 1,
author : 1
}
}
]);
$match
接收一个条件json对象筛选匹配的文档
1
2
3
db.article.aggregate([
{ $match : { score : { $gt : 70, $lte : 90 } } }
]);
$skip
下一个管道跳过指定数量文档
1
2
3
db.article.aggregate([
{ $skip : 5 }
]);
$limit
指定输入下一个管道的文档数量
1
2
3
db.article.aggregate([
{ $limit: 5 }
]);
$unwind
将文档中的某一个数组类型字段拆分成多个文档,每个文档的该字段为数组中的一个值,指定数组字段时在前面加$
1
2
3
4
5
6
7
8
9
10
11
// ages: [1, 2, 3]
db.article.aggregate([
{ $unwind: "$ages" }
])
// result
[
{ _id: ObjectId('66526805ab4236a343cdcdf6'), ages: 1 },
{ _id: ObjectId('66526805ab4236a343cdcdf6'), ages: 2 },
{ _id: ObjectId('66526805ab4236a343cdcdf6'), ages: 3 }
]
$sort
将文档排序后输出
1
2
3
4
5
6
7
8
db.article.aggregate([
{
"$sort": {
"pop": -1, // 降序
"city": 1 // 升序
}
}
])
$group
将集合中的文档分组,可以使用聚合操作符来统计结果,接收的json对象包含两类字段
_id
:指定分组的字段,字段前加$
- field:自定义聚合结果字段名,接收一个json对象,其中使用聚合操作符作为key,聚合字段作为value
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
db.article.aggregate([
{
$group: {
_id: "$state", // 按state字段分组
totalPop: {
$sum: "$pop" // 统计pop字段总和,结果字段为totalPop
},
avgPop: {
$avg: "$pop" // 统计pop字段的平均值,结果字段为avgPop
},
count: {
$sum: 1 // 统计每个分组的文档数量,结果字段为count
}
}
}
])
常用聚合操作符如下
表达式 | 描述 |
---|---|
$sum | 计算总和 |
$avg | 计算平均值 |
$min | 获取集合中所有文档指定字段的最小值 |
$max | 获取集合中所有文档指定字段的最大值 |
$push | 将值加入一个数组中,不会判断是否有重复的值 |
$addToSet | 将值加入一个数组中,会判断是否有重复的值,若相同的值在数组中已经存在了,则不加入 |
$first | 根据文档的排序获取第一个文档数据 |
$last | 根据文档的排序获取最后一个文档数据 |
数据库引用
mongodb中不支持连接查询,在文档使用三个特殊字段来引用其他文档
引用的基本格式
1
2
3
4
5
{
$ref: "collection_name",
$id: ObjectId("..."),
$db: "db_name"
}
e.g. 在user文档中引用address文档
1
2
3
4
5
6
7
8
9
10
11
{
"_id": ObjectId("53402597d852426020000002"),
"address": {
"$ref": "address_home",
"$id": ObjectId("534009e4d852427820000002"),
"$db": "runoob"
},
"contact": "987654321",
"dob": "01-01-1991",
"name": "Tom Benzamin"
}
在查询时需要分步查询
1
2
3
var user = db.users.findOne({"name":"Tom Benzamin"})
var dbRef = user.address
db[dbRef.$ref].findOne({"_id":ObjectId(dbRef.$id)})
ObjectId
mongodb中默认使用ObjectId对象来作为_id
字段的值,ObjectId是一个12字节BSON类型数据,有以下格式
- 前4个字节表示时间戳
- 接下来的3个字节是机器标识码
- 紧接的2个字节由进程id组成(PID)
- 最后3个字节是随机数
调用ObjectId()
创建ObjectId,mongodb会自动生成一个唯一id
1
var newObjectId = ObjectId()
ObjectId中存储了4个字节的时间戳,getTimestamp()
来获取时间戳
1
2
var myId = ObjectId()
myId.getTimestamp()