在使用 MongoDB 时,您可能会遇到需要通过一次操作更新多个文档的情况。虽然可以遍历文档逐个更新,但 updateMany 提供了更快捷、更高效的解决方案。
在这篇简短的教程中,我们将学习如何在 MongoDB 中使用 updateMany 操作符,并优化查询以获得尽可能好的性能。
如果您想用 Python 夯实 MongoDB 的数据处理基础,建议查看课程 Introduction to MongoDB in Python 。
通过一个实际示例更新多个 MongoDB 文档
为便于说明,我们来看一个实际场景,您可能希望一次更新多个文档。
以下数据将作为我们的示例基础:
[
{ "name" : "Nic Raboy" , "title" : "Master of Shenanigans" , "salary" : 50000 , "last_raise_date" : new Date("2013-06-01" ) } ,
{ "name" : "Megan Grant" , "title" : "Word Wrangler" , "salary" : 125000 , "last_raise_date" : new Date("2020-12-01" ) } ,
{ "name" : "Tony Kim" , "title" : "Alliance Czar" , "salary" : 80000 , "last_raise_date" : new Date("2025-02-01" ) } ,
] ;技术支持
在上述 JSON 中,我们有一家虚构公司的三位员工。公司希望对一段时间内未调整薪资的员工进行补偿性涨薪。
要更新所有符合条件的员工,我们可以使用 MongoDB 的 updateMany 操作符。为完成任务,我们可能会写出如下语句:
db. employees. updateMany (
{
"last_raise_date" : {
"$lte" : new Date ( "2024-01-01" )
}
} ,
{
"$mul" : { "salary" : 1.06 } ,
"$set" : { "last_raise_date" : new Date ( ) }
}
) ; 技术支持
那么,上述 updateMany 操作在做什么呢?
先回到基础,updateMany 接受两个参数,以及一个可选的第三个参数。
第一个参数是一个对象,表示我们要用于筛选的数据。
第二个参数是我们希望对筛选结果进行的更改。
可选的第三个参数可以是 { “upsert”: true },当没有匹配项时会插入一条文档。
基于此,我们首先筛选所有 last_raise_date 早于 "2024-01-01" 的文档。回看我们非常基础的数据集,可以知道有三条中的两条匹配:
[
{ "name" : "Nic Raboy" , "title" : "Master of Shenanigans" , "salary" : 50000 , "last_raise_date" : new Date("2013-06-01" ) } ,
{ "name" : "Megan Grant" , "title" : "Word Wrangler" , "salary" : 125000 , "last_raise_date" : new Date("2020-12-01" ) }
] ;技术支持
根据更改条件参数,针对筛选出的文档会进行两项不同的更改。
"$mul" : { "salary" : 1.06 } , 技术支持
首先,我们使用 $mul 操作符将某个字段乘以一个数值。在本例中,我们希望为每位符合条件的员工加薪 6%。这意味着我们只需将该字段的当前值乘以 1.06。
为帮助记录此次加薪并防止未来的误加,我们还要将 last_raise_date 更新为当前日期:
"$set" : { "last_raise_date" : new Date() } 技术支持
如果我们再次运行 updateMany 操作,将不会发生任何变化,因为筛选条件中的 last_raise_date 将不再匹配我们的三条文档中的任何一条。
以上只是一个示例,您的筛选条件可以复杂得多,同样,您计划进行的更改也可能更复杂,视具体用例而定。您可以在这段视频 中进一步了解 MongoDB 的 updateMany。
通过 MongoDB 索引提升更新性能
在本例中,我们只处理了三条小文档。基本上,无论我们对集合执行什么操作,都很快,因为数据量不大。然而,在生产应用中,您可能要处理数百万条文档,或者频繁运行更新操作。
如果我们尝试对数百万条文档使用 updateMany 操作符,除非为筛选条件建立了合适的索引,否则可能会花费较长时间。
要为本例创建索引,可以执行类似如下的语句:
db. employees. createIndex ( { "last_raise_date" : 1 } ) ; 技术支持
您可以通过执行以下命令验证 updateMany 是否使用了我们的索引:
db. runCommand ( {
"explain" : {
"update" : "employees" ,
"updates" : [
{
"q" : {
"last_raise_date" : {
"$lte" : new Date ( "2024-01-01" )
}
} ,
"u" : {
"$mul" : { "salary" : 1.06 } ,
"$set" : { "last_raise_date" : new Date ( ) }
}
}
]
} ,
"verbosity" : "allPlansExecution"
} ) ; 技术支持
在结果中,如果 inputStage 为 "IXSCAN",则说明您正在使用索引并最大化 updateMany 的性能。如果 inputStage 为 "COLLSCAN",则说明未使用索引,您可能需要根据筛选条件重新考虑索引的建立方式。
为避免混淆,以上我们使用 runCommand 来分析批量更新操作的执行情况。如果您不需要分析信息,直接使用更简单、更优雅的 updateMany 即可。
总结
如本教程所示,在 MongoDB 中用一次操作更新多个文档并不困难。
借助 updateMany 操作符,我们可以定义用于匹配文档的筛选条件,以及包含要进行更改列表的更改条件。通过确保针对筛选条件建立了合适的索引,还可以进一步优化 updateMany 的性能。
如果您刚接触非关系型数据库, Introduction to NoSQL 课程提供了关于文档存储等概念的有用概览。
在使用 MongoDB 时,您可能会遇到需要通过一次操作更新多个文档的情况。虽然可以遍历文档逐个更新,但
updateMany提供了更快捷、更高效的解决方案。在这篇简短的教程中,我们将学习如何在 MongoDB 中使用 updateMany 操作符,并优化查询以获得尽可能好的性能。
如果您想用 Python 夯实 MongoDB 的数据处理基础,建议查看课程 Introduction to MongoDB in Python。
通过一个实际示例更新多个 MongoDB 文档
为便于说明,我们来看一个实际场景,您可能希望一次更新多个文档。
以下数据将作为我们的示例基础:
在上述 JSON 中,我们有一家虚构公司的三位员工。公司希望对一段时间内未调整薪资的员工进行补偿性涨薪。
要更新所有符合条件的员工,我们可以使用 MongoDB 的
updateMany操作符。为完成任务,我们可能会写出如下语句:那么,上述
updateMany操作在做什么呢?先回到基础,
updateMany接受两个参数,以及一个可选的第三个参数。{ “upsert”: true },当没有匹配项时会插入一条文档。基于此,我们首先筛选所有
last_raise_date早于 "2024-01-01" 的文档。回看我们非常基础的数据集,可以知道有三条中的两条匹配:根据更改条件参数,针对筛选出的文档会进行两项不同的更改。
首先,我们使用
$mul操作符将某个字段乘以一个数值。在本例中,我们希望为每位符合条件的员工加薪 6%。这意味着我们只需将该字段的当前值乘以 1.06。为帮助记录此次加薪并防止未来的误加,我们还要将
last_raise_date更新为当前日期:如果我们再次运行
updateMany操作,将不会发生任何变化,因为筛选条件中的last_raise_date将不再匹配我们的三条文档中的任何一条。以上只是一个示例,您的筛选条件可以复杂得多,同样,您计划进行的更改也可能更复杂,视具体用例而定。您可以在这段视频中进一步了解 MongoDB 的 updateMany。
通过 MongoDB 索引提升更新性能
在本例中,我们只处理了三条小文档。基本上,无论我们对集合执行什么操作,都很快,因为数据量不大。然而,在生产应用中,您可能要处理数百万条文档,或者频繁运行更新操作。
如果我们尝试对数百万条文档使用
updateMany操作符,除非为筛选条件建立了合适的索引,否则可能会花费较长时间。要为本例创建索引,可以执行类似如下的语句:
您可以通过执行以下命令验证
updateMany是否使用了我们的索引:在结果中,如果
inputStage为 "IXSCAN",则说明您正在使用索引并最大化updateMany的性能。如果inputStage为 "COLLSCAN",则说明未使用索引,您可能需要根据筛选条件重新考虑索引的建立方式。为避免混淆,以上我们使用
runCommand来分析批量更新操作的执行情况。如果您不需要分析信息,直接使用更简单、更优雅的updateMany即可。总结
如本教程所示,在 MongoDB 中用一次操作更新多个文档并不困难。
借助
updateMany操作符,我们可以定义用于匹配文档的筛选条件,以及包含要进行更改列表的更改条件。通过确保针对筛选条件建立了合适的索引,还可以进一步优化updateMany的性能。如果您刚接触非关系型数据库, Introduction to NoSQL 课程提供了关于文档存储等概念的有用概览。