mongodb更新嵌套数组的值
概要
本文主要讲述在 mongodb 中,怎么更新嵌套数组的值。
使用$更新数组
- 基本语法 { "<array>.$" : value }
- 可以用于:update, findAndUpdate 等方法
- $是一个占位符一样的存在。代表被匹配的数组中的一个元素
- 可以匹配一个数组,匹配多个是会异常 index 0: 2 - Too many positional (i.e. "$") elements found in path ... ,即:只能在一层嵌套的数组中使用 $
- 示例
db.collection.update(
{ <array
>: value ... },{ <update operator
>: { "<array>.$" : value } })
测试
- 创建一个测试数据
for (let i = 0; i < 3; i++) {
let data
= {name1_1: "test"
+ i,arr_1: [{
a: i,
b:
2}, {
a: i
+ 1,b:
2}]
};
db.nestedUpdate.insert(data);
}
创建数据脚本
数据截图:
- 我想更新arr_1数组中,a = 1 的对象,更新为 {a:11,b:12} 运行更新代码,如下:
db.nestedUpdate.updateMany({
"arr_1.a":
1}, {
$set: {"arr_1.
$.a": 11,"arr_1.
$.b": 12,}
})
运行后数据截图:
- 针对上述结构,更新 a= 11 的对象值(与上面不同,上面是更新对象里面的一个值),运行一下代码:
db.nestedUpdate.updateMany({
"arr_1.a":
11}, {
$set: {
"arr_1.$": {a:11, c:[1,2,3]}
} })运行结果:
继续编辑,修改 arr_1.c 的元素,很容易想到如下:
db.nestedUpdate.updateMany({
"arr_1.c":
1}, {
$set: {"arr_1.
$.$": 11,}
})
然而,最终的运行结果却是: [Error] index 0: 2 - Too many positional (i.e. "$") elements found in path "arr_1.$.$"
那么,我想更新数组中的数组下的一个元素这么办呢?下面介绍两种方法:1、遍历数组修改,2、使用 arrayFilter。个人推荐 arrayFilter 方式。
.find.foreach + save (循环判断保存法)
- 通过 .find 找到满足条件的集合,(但只能找到根节点)
- 遍历需要修改的节点,修改其值,(先遍历arr_1, 在遍历 arr_1.c)
- 把修改完成的对象,通过 save 方法更新回数据库。
- 代码如下
// 查找所有
var all1
= db.nestedUpdate.find({});all1.
forEach(function(it) {var modified
= false;// 遍历 arr_1for (var i = 0; i < it.arr_1.length; ++i) {var ac1
= it.arr_1[i];// 判断需要修改的if (ac1.c && ac1.c.length > 0 && ac1.c[0] == 1) {ac1.c[
0] = 1111;modified
= true;}
}
if (modified) {db.nestedUpdate.save(it);
}
})
利用arrayFilter
- 基本语法
db.collection.updateMany({ <query conditions
> },{ <update operator
>: { "<array>.$[<identifier>]" : value } },{ arrayFilters: [ { <identifier
>: <condition> } ] })
- 官方文档地址:https://docs.mongodb.com/manual/reference/operator/update-array/
如上,建立一个示例,把 arr_1.c的值改回去
注意
- arrayFilter 数组中的顶级字段不能重复,如下:出现了两个 idx0,运行报错 index 0: 9 - Found multiple array filters with the same top-level field name idx0
db.nestedUpdate.updateMany({}, {$set: {
"arr_1.
$[idx0].c.$[idx1]": 1}
}, {
arrayFilters: [
{
// idx0 满足条件: 需存在 c 字段"idx0.c": {
$exists: true},
},
{
"idx0.a":
1,},
{
// idx1: 满足 值为 111"idx1":
1111}
]
});
> [Error] index 0: 9 - Found multiple array filters with the same top-level field name idx0at line
1, column 1View Code
- arrayFilter 中可以嵌套条件,如:
db.nestedUpdate.updateMany({}, {$set: {
"arr_1.
$[idx0].c.$[idx1]": 1}
}, {
arrayFilters: [
{
// idx0 满足条件: 需存在 c 字段"idx0.c": {
$exists: true},
"idx0.a":
1,},
{
// idx1: 满足 值为 111"idx1":
1111}
]
});
// 或db.nestedUpdate.updateMany({}, {
$set: {"arr_1.
$[idx0].c.$[idx1]": 1}
}, {
arrayFilters: [
{
// idx0 满足条件: 需存在 c 字段idx0: {
c: {
$exists: true},
a:
1}
},
{
// idx1: 满足 值为 111"idx1":
1111}
]
});
View Code
- arrayFilter 必须包含所有的索引的条件。否则出现错误 [Error] index 0: 2 - No array filter found for identifier "idx2" in path "arr_1.$[].arr_1_1.$[idx1].arr1_1_1.$[idx2]"
db.nestedUpdate1.updateMany({}, {$set: {
"arr_1.
$[].arr_1_1.$[idx1].arr1_1_1.$[idx2]": null}
}, {
arrayFilters: [
{
// idx1: 满足 name <= 1"idx1.name": {
$lte: 1}
},
]
})
> [Error] index 0: 2 - No array filter found for identifier "idx2" in path "arr_1.$[].arr_1_1.$[idx1].arr1_1_1.$[idx2]"at line
1, column 1> 时间: 0.003s
完整代码
- $[idx] 中的idx 可以自定义名字,只需要arrayFilter中名字一样就可以,如 $[i], $[j]
- 不止updateMany可以用,update、findAndUpdate、findAndModify 等也可以用
- 可以与$[] 一起使用,需保证数组中的所有元素都满足后面的条件,如:
db.nestedUpdate1.updateMany({}, {$set: {
"arr_1.
$[].arr_1_1.$[idx1].arr1_1_1.$[idx2]": null}
}, {
arrayFilters: [
{
// idx1: 满足 name <= 1"idx1.name": {
$lte: 1}
},
{
idx2:
1}
]
})
运行示意:
以上是 mongodb更新嵌套数组的值 的全部内容, 来源链接: utcz.com/z/532006.html