mongodb - 更新嵌套数组的字段时,如何使 mongodb 的“更新”停止?
问题描述
我有一个这样的数据库:
{
"universe":"comics",
"saga":[
{
"name":"x-men",
"characters":[
{
"character":"wolverine",
"picture":"618035022351.png"
},
{
"character":"wolverine",
"picture":"618035022352.png"
}
]
}
]
},
{
"universe":"dc",
"saga":[
{
"name":"spiderman",
"characters":[
{
"character":"venom",
"picture":"618035022353.png"
}
]
}
]
}
使用这段代码,我更新了 where 字段name: wolverine
:
db.getCollection('collection').findOneAndUpdate(
{
"universe": "comics"
},
{
$set: {
"saga.$[outer].characters.$[inner].character": "lobezno",
"saga.$[outer].characters.$[inner].picture": "618035022354.png"
}
},
/*{
"saga.characters": 1
},*/
{
"arrayFilters": [
{
"outer.name": "x-men"
},
{
"inner.character": "wolverine"
}
],
"multi":false
}
)
我只想更新第一个匹配的对象,然后停止它。
例如,如果我有一个包含 100,000 个元素的数组,并且匹配的对象位于第十位,他将更新该记录,但他将继续遍历整个数组,这对我来说似乎无效,即使他已经做了更新。
注意:如果我使用_id
inside 进行 universe.saga.characters
更新而不是使用 进行更新name
,它仍然会循环遍历其余元素。
我该怎么做?
解决方案
使用arrayFilters
条件更新
我不认为它会通过循环查找和更新,如果集合有 100,000 个子文档也没关系,因为这里在$[<identifier>]中有很好的解释,并提到:
$[<identifier>]
定义一个标识符,只更新那些匹配对应过滤器文档的数组元素arrayFilters
在更新文档中,使用
$[<identifier>]
过滤后的位置运算符定义一个标识符,然后在数组过滤器文档中引用该标识符。但是,如果标识符未包含在更新文档中,请确保您不能拥有标识符的数组过滤文档。
使用更新_id
你的观点,
注意:如果我使用
_id
内部universe.saga.characters
而不是使用名称进行更新,它仍然会循环遍历其余元素。
MongoDB 肯定会使用_id
索引。这是关于MongoDB Update Query Performance问题的不错答案,从这里您将对上述问题有更好的了解
使用索引字段更新
您可以根据更新命令的查询部分创建索引,这里MongoDB Indexes and Indexing Strategies解释了为什么索引很重要,
在您的示例中,让我们看一下示例:
示例 1:如果文档有 2 个子文档,并且当您使用explain("executionStats")更新和检查时,假设更新需要 1 秒,
快速使用Mongo Playground (本平台不支持更新查询)
示例 2:如果文档有 1000 个子文档,并且当您使用explain("executionStats")更新和检查时,可能需要超过 1 秒,
如果在字段(和)上提供索引
universe
,那么肯定会比没有索引花费更少的时间,索引的主要好处是它将直接指向索引字段。saga.characters.character
saga.characters.picture
快速使用Mongo Playground (本平台不支持更新查询)
为您的字段创建索引
db.maxData.createIndex({
"universe": 1,
"saga.characters.character": 1,
"saga.characters.picture": 1
})
如需更多实验,请使用以上 2 个带索引和不带索引的示例数据,并检查
executionStats
您将获得更清晰的结果。
推荐阅读
- css - 如何使用 css 网格做与此类似的事情?
- git - 撤消本地文件更改的不同命令
- geojson - Turf - 获取 geojson 的所有特征,这些特征在一个点的范围内
- database - 如何在 dynamoDB、嵌套字典或多个项目中构造数据?
- oracle - 从 Oracle 中的标准输入复制
- android - Android上的libvlc“图片来不及显示”错误
- c# - 在 C# 程序中使用“Microsoft.Office.Interop.Word”时,语法检查不适用于感叹句
- javascript - js:在文档中的所有 div 上进行 for 循环,以在每个 div 中添加一个新的 div —— for 循环包括新添加的 div
- css - 如何修复当输入类型从“文本”更改为“类型”时更改的 Form.control 输入宽度?
- java - DatumFactory 不是 ImageIO SPI 类