开始
什么是MongoDB
MongoDB,一种非关系型数据库,使用JSON样式的文档模型存储数据,适合非结构化数据的场景。
官网:https://www.mongodb.com/zh-cn
官方文档:https://www.mongodb.com/zh-cn/docs/manual/
特点:
- 文档模型
基于集合的文档存储方式。 - 灵活的模式
无需预定义模式,支持动态添加字段。 - 丰富的查询方式。
- 多语言驱动支持
官方支持多种编程语言的驱动程序,包括Java、Python、C#、Ruby等。 - BSON数据格式
内部使用BSON(Binary JSON)格式存储数据,相较于纯文本JSON更加紧凑和高效。 - 分布式架构:副本、分片
- ACID事务
从4.0开始引入多文档ACID事务。 - 内置聚合框架
用于执行复杂的数据分析任务,例如过滤、排序、分组等。 - 索引
支持创建各种类型的索引来加速查询,并提供性能监控工具帮助调优。
安装
本文以在Linux(Rocky)上安装MongoDB为例。
添加MongoDB仓库
因为Linux(Rocky)的官方仓库中没有MongoDB的软件包,所以我们需要先添加MongoDB的官方仓库。
在/etc/yum.repos.d/
目录下,创建文件mongodb-org-8.0.repo
,内容如下:
1 | [mongodb-org-8.0] |
注意:本文以MongoDB-8.0
的仓库为例,如果需要安装其他版本的MongoDB,需要修改相应的仓库地址和版本号。
mongodb-org-8.0.repo
文件创建完成后,执行如下命令,更新仓库缓存:
1 | dnf makecache |
安装MongoDB
安装MongoDB,命令如下:
1 | dnf install -y mongodb-org |
安装完成后,我们可以通过如下命令,查看MongoDB的版本信息:
1 | mongod --version |
运行结果:
1 | db version v8.0.3 |
配置
启动MongoDB服务
先启动MongoDB服务,启动命令:
1 | systemctl start mongod |
配置管理员账户
执行如下命令,连接MongoDB:
1 | mongosh |
注意:在早期版本的命令是mongo
,在较新版本的命令是mongosh
。
示例代码:
1 | mongosh |
运行结果:
1 | Current Mongosh Log ID: 675298fb8b94b55a9fe94969 |
通过use 【数据库】
,切换到admin数据库,示例代码:
1 | use admin |
运行结果:
1 | switched to db admin |
创建一个名为admin,密码为password的管理员账户,示例代码:
1 | db.createUser({user: "admin", pwd: "password", roles: ["root"]}) |
运行结果:
1 | { ok: 1 } |
创建完成后,退出连接,示例代码:
1 | exit |
开启权限校验
修改/etc/mongod.conf
,找到如下内容:
1 | #security: |
修改为:
1 | security: |
重启MongoDB服务,示例代码:
1 | systemctl restart mongod |
此时,如果我们直接通过mongosh
连接,不含有用户名密码等参数,并执行show databases;
的话,返回如下,没有权限。
1 | MongoServerError[Unauthorized]: Command listDatabases requires authentication |
登录命令如下:
1 | mongosh -u admin -p password --authenticationDatabase admin |
允许远程连接
修改/etc/mongod.conf
,,找到如下内容:
1 | # network interfaces |
将bindIp: 127.0.0.1
修改为bindIp: 0.0.0.0
。
一些概念
在数据库、表、集合等方面,MongoDB和传统关系型数据库之间的对应关系如下:
RDBMS | MongoDB |
---|---|
数据库 database | 数据库 database |
表 table | 集合 collection |
行 row | 文档 document |
列 column | 字段 field |
新增、更新和删除
库
查看所有库
两种方式查看所有库:
show databases;
show dbs;
示例代码:
1 | show databases; |
运行结果:
1 | admin 132.00 KiB |
创建数据库
创建数据库:use 【库名】
示例代码:
1 | use kaka |
运行结果:
1 | switched to db kaka |
然后我们执行show dbs
,会发现居然没有kaka
这个库,示例代码:
1 | show dbs; |
运行结果:
1 | admin 132.00 KiB |
use
代表创建并使用,当库中没有数据时默认不显示这个库。
我们插入一条数据,示例代码:
1 | db.users.insertOne({"id":1}) |
运行结果:
1 | { |
再看一下,会发现这时候有kaka
这个库了。示例代码:
1 | show dbs; |
运行结果:
1 | admin 132.00 KiB |
删除数据库
删除数据库:db.dropDatabase()
- 删除的是当前选中的库。
- 可以通过
db
命令,查看当前库。
示例代码:
1 | db |
运行结果:
1 | kaka |
示例代码:
1 | db.dropDatabase(); |
运行结果:
1 | { ok: 1, dropped: 'kaka' } |
集合
查看库中所有集合
两种方式查看库中所有集合:
show collections;
show tables;
创建集合
创建集合:db.createCollection('【集合名称】', [options])
注意:当集合不存在时,向集合中插入文档也会自动创建该集合。
options
可以是如下参数:
capped
布尔
如果为true,则创建固定大小的集合。当达到最大值时,它会自动覆盖最早的文档。当该值为true时,必须指定size参数。size
数值
为固定大小集合指定一个最大值,字节数。max
数值
指定固定集合中包含文档的最大数量。capped
和size
参数是必须一起指定的;max
参数则是可选的,用于进一步限制集合中可以包含的最大文档数量。
示例代码:
1 | db.createCollection("logs", { |
运行结果:
1 | { ok: 1 } |
查看集合信息
查看集合信息:db.【集合名称】.stats()
上述命令会返回很多内容,如果我们只关注capped
、size
和max
,可以做过滤输出:
1 | var stats = db.logs.stats(); |
删除集合
删除集合:db.【集合名称】.drop();
文档
插入文档
插入单条文档
插入单条文档:
1 | db.【集合名称】.insertOne( |
示例代码:
1 | db.users.insertOne( |
插入多条文档
插入多条文档:
1 | db.【集合名称】.insertMany( |
示例代码:
1 | db.user.insertMany( |
运行结果:
1 | { |
可选参数
可选参数主要有如下:
1 | // 写入关注(writeConcern)定义了MongoDB在报告成功之前需要满足的写入确认级别。 |
- 其中
ordered
是插入多条文档参会有的。
示例代码:
1 | db.user.insertMany( |
删除
删除单条文档
删除单条文档:
1 | db.【集合名称】.deleteOne( |
示例代码:
1 | // 从 user 集合中删除第一个匹配到的名为 "kaka" 的文档。 |
运行结果:
1 | { acknowledged: true, deletedCount: 1 } |
解释说明:deletedCount: 1
,表示成功删除了1个文档。
删除多条文档
删除多条文档:
1 | db.【集合名称】.deleteMany( |
示例代码:
1 | // 从 user 集合中删除所有年龄大于30岁的文档,并指定写入关注。 |
运行结果:
1 | { acknowledged: true, deletedCount: 1 } |
可选参数
与插入文档的可选参数几乎一致,不再赘述。
更新
更新单条文档
更新单条文档:
1 | db.【集合名称】.updateOne( |
示例代码:
1 | // 从 user 集合中找到第一个名为 "kaka" 的文档,并将其年龄更新为31。 |
运行结果:
1 | { |
解释说明:
acknowledged
- 类型:布尔值
- 描述:指示操作是否被服务器确认。
如果为true
,则表示客户端收到了来自MongoDB服务器的成功确认;如果为false
,则可能意味着使用了writeConcern配置为不需要确认,或者发生了某些错误导致操作未被确认。
insertedId
- 类型:ObjectId或
null
- 描述:当设置了
upsert: true
并且没有匹配到现有文档时,此字段会包含新插入文档的_id
值。
在上文的该字段为null
,这表明并没有发生插入操作,即要么是更新了一个已存在的文档,要么是没有启用upsert
选项。
- 类型:ObjectId或
matchedCount
- 类型:数字
- 描述:表示根据查询条件匹配到的文档数量。
modifiedCount
- 类型:数字
- 描述:表示实际被修改的文档数量。
upsertedCount
- 类型:数字
- 描述:表示由
upsert
操作新插入的文档数量。
如果我们操作启用了upsert
选项并且没有找到匹配的文档,那么MongoDB将插入一条新记录,并且这个计数器将增加。
更新多条文档
更新多条文档:
1 | db.【集合名称】.updateMany( |
示例代码:
1 | // 将 user 集合中所有年龄大于等于30岁的用户的职业更新为 "Senior Engineer"。 |
运行结果:
1 | { |
replaceOne
替换单条文档:
1 | db.【集合名称】.replaceOne( |
与updateOne
不同,replaceOne
方法用全新的文档替换掉匹配到的第一个文档。
示例代码:
1 | // 从 user 集合中找到第一个名为 "kaka" 的文档,并完全替换为新的文档内容。 |
运行结果:
1 | { |
可选参数
有一个参数是之前没有的,upsert
:
upsert
参数决定了当没有匹配到文档时是否插入新文档。- 如果设置为
true
,则在没有匹配文档的情况下会创建一个新文档。 - 默认为
false
,表示不插入新文档。
示例代码:
1 | // 将 user 集合中所有年龄大于等于30岁的用户的职业更新为 "Senior Engineer"。 |
文档查询
语法
文档查询语法
1 | db.【集合名称】.find(query, projection); |
query
:- 类型:文档(Document)
- 作用:可选参数,使用查询操作符来指定筛选条件。如果不提供查询条件,则默认匹配所有文档。
projection
:- 类型:文档(Document)
- 作用:可选参数,使用投影操作符来指定返回哪些字段。如果省略此参数,默认会返回文档中的所有字段。
格式化输出
为了使查询结果更易于阅读,MongoDB提供了pretty()
方法,可以格式化输出,使文档结构更加清晰易读。
1 | db.【集合名称】.find().pretty(); |
注意,虽然pretty()
方法提高了可读性,但在处理大量数据时可能会导致性能下降,因为需要额外的时间来进行格式化。因此,在生产环境中进行大数据量查询时应谨慎使用。
示例代码
1 | // 返回集合中的所有文档,结果以非格式化形式显示 |
比较运算符
大小关系比较
操作 | 格式 | 范例 | RDBMS中的类似语句 |
---|---|---|---|
等于 | {<key>:<value>} |
db.col.find({"name":"Kaka"}).pretty() |
where name = 'Kaka' |
小于 | {<key>:{$lt:<value>}} |
db.col.find({"age":{$lt:50}}).pretty() |
where age < 50 |
小于或等于 | {<key>:{$lte:<value>}} |
db.col.find({"age":{$lte:50}}).pretty() |
where age <= 50 |
大于 | {<key>:{$gt:<value>}} |
db.col.find({"age":{$gt:50}}).pretty() |
where age > 50 |
大于或等于 | {<key>:{$gte:<value>}} |
db.col.find({"age":{$gte:50}}).pretty() |
where age >= 50 |
不等于 | {<key>:{$ne:<value>}} |
db.col.find({"age":{$ne:50}}).pretty() |
where age != 50 |
数组中查询
假设,存在数据如下:
1 | [ |
查询包含特定元素的数组
查询包含特定元素的数组的文档,可以直接在查询条件中指定该元素。示例代码:
1 | db.user.find({ likes: "阅读" }); |
解释说明:此查询返回所有likes
数组中至少包含"阅读"
这个值的文档。
按数组长度查询
可以使用$size
操作符,根据数组的长度来筛选文档。示例代码:
1 | db.user.find({ likes: { $size: 3 } }); |
解释说明:此查询返回likes
数组正好有三个元素的文档。
其他数组查询操作符
$all
:匹配数组中包含所有给定值的文档。
示例代码:1
2// 查找 likes 数组中同时包含 "阅读" 和 "电影" 的文档
db.user.find({ likes: { $all: ["阅读", "电影"] } });$elemMatch
:匹配数组中至少有一个元素同时满足多个条件的文档。
示例代码:1
2
3
4
5
6
7
8
9// 查找 likes 数组中既有评分等于 5 且活动为 "阅读" 的用户
db.user.find({
likes: {
$elemMatch: {
activity: "阅读",
rating: 5
}
}
});$in
和$nin
:分别用于匹配数组中包含或不包含指定值的文档。
示例代码:1
2
3
4
5// 查找 likes 数组中包含 "阅读" 或 "电影" 的文档
db.user.find({ likes: { $in: ["阅读", "电影"] } });
// 查找 likes 数组中既不包含 "阅读" 也不包含 "电影" 的文档
db.user.find({ likes: { $nin: ["阅读", "电影"] } });
模糊查询
正则表达式
在关系型数据库中,我们"LIKE"语句来执行模糊匹配查询。
MongoDB提供了类似的功能,但是通过正则表达式(Regular Expressions,RegEx)来实现的。
例子
假设存在一批数据,如下:
1 | // 创建 products 集合并插入测试数据 |
- 查询包含特定子串的商品,区分大小写,示例代码:解释说明:这条命令返回
1
2// 查找 description 中包含 "powerful" 的商品
db.products.find({ description: /powerful/ });description
字段中包含"powerful"的商品,并且是区分大小写的。 - 忽略大小写的模糊查询,
/i
标志指定了忽略大小写,示例代码:解释说明:这条命令返回所有1
db.products.find({ name: /laptop/i });
name
字段中包含"laptop"的商品,/i
标志指定了忽略大小写。 - 查询以特定子串开头的商品,示例代码:解释说明:这条命令返回
1
2// 查找 name 以 "Smart" 开头的商品
db.products.find({ name: /^Smart/ });name
字段以"Smart"开头的商品。 - 查询以特定子串结尾的商品,示例代码:解释说明:这条命令返回
1
2// 查找 description 以 "work" 结尾的商品
db.products.find({ description: /work$/ });description
字段以"work"结尾的商品。
多个条件组合的模糊查询
我们还可以结合其他查询条件与正则表达式一起使用,以实现更精细的筛选。示例代码:
1 | // 查找 description 包含 "wireless" 且 name 包含 "headphones" 的商品,忽略大小写 |
逻辑运算符
假设存在一批数据如下:
1 | // 创建 books 集合并插入测试数据 |
AND运算符
我们可以在同一查询条件中指定多个键值对,这些键值对条件将通过逻辑AND
组合起来的。
查找出版年份为1949年且类型为"Dystopian"的书籍,示例代码:
1 | // 查找 year = 1949 并且 genre = "Dystopian" 的书籍 |
OR运算符
$or
操作符使用方法:将不同的条件放入一个数组中,并将其作为$or
的值传递给查询条件。
查找作者为"George Orwell"或类型为"Romance"的书籍,示例代码:
1 | // 查找 author = "George Orwell" 或 genre = "Romance" 的书籍 |
结合AND和OR运算符
查找出版年份大于1950年,并且作者为"George Orwell"或类型为"Dystopian"的书籍,示例代码:
1 | // 查找 year > 1950 并且 (author = "George Orwell" 或 genre = "Dystopian") 的书籍 |
排序
MongoDB提供了sort()
方法指定一个或多个字段,并提供了升序(1
)和降序(-1
)两种排序方式。
示例代码:
1 | // 按 category 升序, publishedDate 降序排序 |
分页
MongoDB提供了skip()
和limit()
方法来实现分页,类似于SQL中的LIMIT
语句。
示例代码:
1 | // 获取第 2 页的数据,每页 2 条记录,按 publishedDate 降序排序 |
统计总条数
MongoDB提供了countDocuments()
方法用于统计符合查询条件的文档数量。
示例代码:
1 | // 统计所有文档的数量 |
去重
MongoDB提供了distinct()
方法用于返回集合中某个字段的所有不同值,类似于SQL中的SELECT DISTINCT
语句。
示例代码:
1 | // 获取 author 字段的所有不同值 |
指定返回字段
投影的基本规则
有时我们只需要查询文档中的某些特定字段,而不是整个文档。MongoDB通过投影(projection)功能来实现这一点,允许我们在查询时指定哪些字段应该被包含或排除。
基本规则:
- 包含某些字段
如果我们想指定哪些字段应该被包含在结果中,可以将这些字段设置为1
。 - 排除某些字段
如果我们想指定哪些字段不应该出现在结果中,可以将这些字段设置为0
。 _id
字段的特殊性
默认情况下,MongoDB总是会返回_id
字段,除非我们明确地将其设置为0
。
投影的注意事项
- 不能同时使用
1
和0
在一个投影对象中,不能同时使用1
和0
来指定字段。
唯一的例外是_id
字段,可以与其他字段一起被指定为0
。 - 包含所有其他字段
如果指定了一个或多个字段为1
,则只有这些字段会被返回,而其他所有字段将被排除。 - 排除所有其他字段
如果指定了一个或多个字段为0
,那么这些字段将被排除,而其他所有字段将被包含。
例子
1 | // 只返回 title 和 category 字段,不返回 _id 字段 |
1 | // 返回所有字段,但不返回 publishedDate 字段 |
如果同时指定1
和0
,会报错。示例代码:
1 | // 返回 title 和 category 字段,不返回 author 字段和 _id 字段 |
运行结果:
1 | MongoServerError[Location31254]: Cannot do exclusion on field author in inclusion projection |
$type
作用
$type
操作符是基于BSON类型来检索集合中匹配的数据类型,并返回结果。
MongoDB中可以使用的类型如下表所示:
类型名称 | 数值代码 | 字符串别名 | 注意 |
---|---|---|---|
Double | 1 |
"double" |
|
String | 2 |
"string" |
|
Object | 3 |
"object" |
|
Array | 4 |
"array" |
|
Binary Data | 5 |
"binData" |
|
Undefined | 6 |
"undefined" |
已废弃。 |
ObjectId | 7 |
"objectId" |
|
Boolean | 8 |
"bool" |
|
Date | 9 |
"date" |
|
Null | 10 |
"null" |
|
Regular Expression | 11 |
"regex" |
|
DBPointer | 12 |
"dbPointer" |
已弃用。 |
JavaScript | 13 |
"javascript" |
|
Symbol | 14 |
"symbol" |
已废弃,建议使用字符串。 |
Int32 (32-bit Integer) | 16 |
"int" |
|
Timestamp | 17 |
"timestamp" |
|
Int64 (64-bit Integer) | 18 |
"long" |
|
Decimal128 | 19 |
"decimal" |
|
MinKey | -1 |
"minKey" |
|
MaxKey | 127 |
"maxKey" |
注意事项:
- Undefined、DBPointer和Symbol类型,这些类型在现代MongoDB中已经不推荐使用或已被废弃。
- JavaScript类型,通常不建议直接在数据库中存储JavaScript代码,除非有特殊需求。
例子
例如,要查找所有price
字段为64位浮点数(Double)的文档:
1 | db.collection.find({ price: { $type: "double" } }); |
或者使用类型代码:
1 | db.collection.find({ price: { $type: 1 } }); |
聚合
例子
假设,存在一批数据如下:
1 | // 创建 events 集合并插入测试数据 |
统计每个组织者的活动数量
示例代码:
1 | db.events.aggregate([ |
运行结果:
1 | [ |
解释说明:
$group
:根据organizer
字段对活动进行分组。totalEvents
:计算每个组织者举办的活动总数。
计算每个城市的总参与人数
示例代码:
1 | db.events.aggregate([ |
运行结果:
1 | [ |
解释说明:
$group
:根据location
字段对活动进行分组。totalAttendees
:计算每个城市所有活动的总参与人数。
找出费用超过一定金额的活动
示例代码:
1 | db.events.aggregate([ |
解释说明:
$match
:筛选出费用大于50.00的活动。$sort
:将结果按照费用降序排列。
限制返回的结果数量
示例代码:
1 | db.events.aggregate([ |
解释说明:
$limit
:确保只返回前3个满足条件的活动。
多阶段聚合查询
找到每个城市中最贵的活动,并且只返回活动名称、费用和城市信息。示例代码:
1 | db.events.aggregate([ |
解释说明:
$group
:根据location
字段对活动进行分组,并找到每个城市中最贵的活动。$project
:重新构建输出文档,只返回活动名称、城市名和最高费用。
常见聚合表达式
表达式 | 描述 | 实例 |
---|---|---|
$sum |
计算总和。 | db.events.aggregate([{$group : {_id : "$organizer", totalLikes : {$sum : "$likes"}}}]) |
$avg |
计算平均值。 | db.events.aggregate([{$group : {_id : "$organizer", avgCost : {$avg : "$cost"}}}]) |
$min |
获取集合中所有文档对应值的最小值。 | db.events.aggregate([{$group : {_id : "$location", minAttendees : {$min : "$attendees"}}}]) |
$max |
获取集合中所有文档对应值的最大值。 | db.events.aggregate([{$group : {_id : "$location", maxCost : {$max : "$cost"}}}]) |
$push |
将值加入一个数组中,不会判断是否有重复的值。 | db.events.aggregate([{$group : {_id : "$organizer", eventNames : {$push: "$name"}}}]) |
$addToSet |
将值加入一个数组中,会判断是否有重复的值,若相同的值在数组中已经存在了,则不加入。 | db.events.aggregate([{$group : {_id : "$organizer", uniqueLocations : {$addToSet : "$location"}}}]) |
$first |
根据资源文档的排序获取第一个文档数据。 | db.events.aggregate([{$sort: {date: 1}}, {$group : {_id : "$organizer", firstEvent : {$first : "$name"}}}]) |
$last |
根据资源文档的排序获取最后一个文档数据。 | db.events.aggregate([{$sort: {date: -1}}, {$group : {_id : "$organizer", lastEvent : {$last : "$name"}}}]) |
解释说明:
$sum
:用于对数值字段进行累加,可以是固定的数值(如1
)或文档中的字段值。$avg
:计算数值字段的平均值。$min
和$max
:分别找出指定字段中的最小值和最大值。$push
:将指定字段的值添加到数组中,允许重复值。$addToSet
:类似于$push
,但会确保数组中的值唯一。$first
和$last
:根据文档的排序顺序,返回分组内第一个或最后一个文档的指定字段值。需要注意的是,在使用这两个操作符时,通常需要先通过$sort
阶段来确定排序规则。
索引
操作索引
创建索引
创建索引:
1 | db.【集合名称】.createIndex(keys, options) |
解释说明:
keys
:一个对象,其键为要索引的字段名,值为升序(1
)或降序(-1
)。1
db.collection.createIndex({ "title": 1, "description": -1 })
options
:一个可选的对象,用于指定索引的各种属性。
options的可选类型有:
参数 | 类型 | 描述 |
---|---|---|
background |
Boolean | 是否以后台方式创建索引,默认为 false 。 |
unique |
Boolean | 是否创建唯一索引,默认为 false 。 |
name |
String | 指定索引的名称。如果不指定,MongoDB 将自动生成一个名称。 |
sparse |
Boolean | 是否对文档中不存在的字段不启用索引,默认为 false 。 |
expireAfterSeconds |
Integer | 设置 TTL(Time To Live)索引,单位为秒。 |
v |
Integer | 索引版本号,默认取决于 mongod 版本。 |
weights |
Document | 文本索引的权重,数值范围在 1 到 99,999 之间。 |
default_language |
String | 文本索引的语言,默认为英语。 |
language_override |
String | 文档中覆盖默认语言的字段名,默认为language 。 |
查看索引
查看索引,getIndexes()
:
1 | db.【集合名称】.getIndexes() |
查看索引占用空间大小
查看索引占用空间大小,totalIndexSize()
:
1 | db.【集合名称】.totalIndexSize() |
删除索引
删除所有索引
删除所有索引,dropIndexes()
:
1 | db.【集合名称】.dropIndexes() |
删除特定索引
删除特定索引,dropIndex()
,传入索引名称:
1 | db.集合名称.dropIndex("索引名称") |
索引分类
- 单字段索引
仅对一个字段创建索引。 - 复合索引
对多个字段创建索引,通常用于支持多字段查询条件。
遵循最左前缀法则(最左前缀原则、最左前缀匹配原则)。
(关于最左前缀匹配原则,可以参考《MySQL从入门到实践:5.索引和优化》) - TTL(Time to Live)索引
用于自动删除过期文档,常用于日志或临时数据存储。
即,在创建索引的options参数中,指定expireAfterSeconds
属性。示例代码:1
db.collection.createIndex({ "createdAt": 1 }, { expireAfterSeconds: 3600 })
- 文本索引
支持全文搜索功能,特别适合处理大量的文本内容。示例代码:1
db.collection.createIndex({ "content": "text" })
- 地理空间索引
支持地理位置相关的查询,如查找附近的地点。示例代码:1
db.collection.createIndex({ "location": "2dsphere" })
关于TTL索引,需要说明的是:
TTL索引在MongoDB中用于自动删除过期的文档,而不是仅仅清理索引条目。
删除过程如下:
- 后台线程处理:MongoDB使用一个后台线程每分钟扫描一次带有TTL索引的集合,查找并删除那些超过生存时间(即
expireAfterSeconds
所指定的时间)的文档。这意味着实际删除操作可能发生在超时之后的一分钟内。 - 文档删除:一旦文档被确定为过期,整个文档将会从集合中被物理删除,不仅仅是对应的索引条目。因此,所有与该文档相关的数据都会被清除,包括任何其他普通索引中的引用。
注意事项:
- 精确度:由于后台线程的周期性检查机制,TTL删除并不是即时发生的;它可能会有一定的延迟,通常不超过一分钟。
- 性能影响:频繁的大规模删除操作可能会对数据库性能产生影响,尤其是在高并发环境下。因此,在设计TTL索引时应考虑到这一点,并进行适当的测试和监控。
- 适用场景:TTL索引非常适合用于日志、会话管理和临时数据存储等需要自动清理过期数据的应用场景。
Java操作
原生
依赖
需要三个依赖,分别是:
org.mongodb.mongodb-driver-core
org.mongodb.bson
org.mongodb.mongodb-driver-sync
1 | <!-- https://mvnrepository.com/artifact/org.mongodb/mongodb-driver-core --> |
例子
1 | package com.kakawanyifan; |
基于SpringBoot
依赖
1 | <dependency> |
MongoRepository
application.properties
1 | mongodb://admin:password@192.168.13.157:27017/testdb?authSource=admin = |
User
1 | package com.kakawanyifan; |
解释说明:
- 使用
@Document
注解指定了对应的MongoDB集合为users
。 - 对主键字段使用了
@Id
注解。 - 与MongoDB集合中命名不一致的属性使用了
@Field
注解指定了实际的字段名。 - 使用Lombok的
@Data
注解自动生成了Setters和Getters。
UserRepository
创建一个对应的Repository
接口UserRepository
,并将其扩展MongoRepository
接口。
1 | package com.kakawanyifan; |
测试类
针对UserRepository
编写一个单元测试类来对其提供的增、删、改、查方法进行测试。
1 | package com.kakawanyifan; |
MongoTemplate
除了通过定义Repository
接口来对MongoDB进行增、删、改、查操作,我们还可以使用更加灵活的MongoTemplate来对MongoDB进行操作。
1 | package com.kakawanyifan; |
Python操作
pymongo
安装pymongo
。
官方文档:https://pymongo.readthedocs.io/en/stable/
PyPi地址:https://pypi.org/project/pymongo
安装命令:pip install pymongo
例子
1 | from pymongo import MongoClient |