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_1
for (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 idx0
at line 1, column 1 - 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
}
]
}); - 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 更新嵌套数组的值的更多相关文章
- C# .NET Core 3.1中使用 MongoDB.Driver 更新嵌套数组元素和关联的一些坑
C# .NET Core 3.1中使用 MongoDB.Driver 更新数组元素和关联的一些坑 前言: 由于工作的原因,使用的数据库由原来的 关系型数据库 MySQL.SQL Server 变成了 ...
- MongoDB按照嵌套数组中的map的某个key无法正常排序的问题
前阵子同事有一个需求: 在一个数组嵌套map的结构中,首先按照map中的某个key进行筛选,再按照map中的某个key进行排序,但是奇怪的是数据总是乱序的. 再检查了代码和数据之后并没有发现什么错误, ...
- 【MongoDB】嵌套数组查询方案
From:http://stackoverflow.com/questions/12629692/querying-an-array-of-arrays-in-mongodb 数据 db.multiA ...
- MongoDB学习笔记~官方驱动嵌套数组对象的更新
回到目录 对于数组对象mongodb本身是支持的,不过对于数组的更新,mongodb的Csharp驱动目前只支持一级,即你的对象里包含数组,而数组又包括数组,这表示两层,这在更新子数组时,Csharp ...
- Vue 嵌套数组 数组更新视图不更新
关于Vue的响应式原理,可以看官方文档或其他资料, https://www.jianshu.com/p/34de360d6035 data里定义了一个数组arr,数组的元素可以是同样格式的数组arrC ...
- .NET 云原生架构师训练营(模块二 基础巩固 MongoDB 更新和删除)--学习笔记
2.5.4 MongoDB -- 更新和删除 整体更新 更新字段 字段操作 数组操作 删除 https://docs.mongodb.com/manual/reference/operator/upd ...
- [C#]想说一说嵌套数组
今天早上,随感而发,随便写了点东西.结果下午的时候看了看评论,吓我一跳.估计是不是写代码的人看散文看得太少了,还是因为现在的人读的书太少了,似乎有有些大惊小怪. 关于Y美女,我声明一下,尽管她很脱俗, ...
- [jQ/PHP]使用JS数组储值的两种情况(提交PHP处理)
---------------------------------------------------------------------------------------------------- ...
- MongoDB——更新操作(Update)c#实现
c#实现 Mongodb存储[文档局部更新] 如下: 递归更新字段 ,构建UpdateDefinition /// <summary> /// 构建更新操作定义 /// &l ...
随机推荐
- laravel5.4 发送SMTP邮件
https://blog.csdn.net/qq_35843527/article/details/77880631 Lumen / Laravel 5.4 使用网易邮箱 SMTP 发送邮件 获取网易 ...
- 2015年热门的国产开源软件TOP 50
2015年热门的国产开源软件TOP 50 开源中国在 2015 年得到了快速的发展,单开源软件收藏量就接近 40000 款,其中不乏优质的国产开源项目.本文从软件的收藏.下载.访问等多角度挑选出了 2 ...
- 使用FormData格式上传图像并预览图片
前言 做项目时,遇到表单中图像需要跟表单一起提交,这样会造成后台没办法接收到图片.后面上网调查后,明白表单提交时是默认application/x-www-form-urlencoded格式,只接受键值 ...
- SuperSocket命令程序集定义
是的,SuperSocket是用反射来查找哪些公开的类实现了基本的命令接口,但是它只在你的AppServer类定义的程序集中查找. 举例来说, 你的 AppServer 定义在程序集 GameServ ...
- Flex AIR Mobile应用性能解决方案
这个flex mobile开发,一般原生开发也许是最合适的方式,但是涉及到跨平台的问题,有精力的团队一般都会逐个基于移动操作系统进行开发.但是如果追求短小,精悍,快速,希望能够跨平台,基于html5 ...
- Python--day62--ORM的使用
4.Django里ORM的使用 1,手动创建数据库 2,在settings.py里面,配置数据库的连接信息 3,在项目/__init__.py告诉Django用pymysql模块代替MySQLdb(不 ...
- tf.train.match_filenames_once()
文件匹配之用 官方解释: 调用样例: https://bbs.csdn.net/topics/392271556 返回值样例:
- linux ioctl 方法
ioctl, 我们在第 1 章展示给你如何使用, 是一个系统调用, 作用于一个文件描述符; 它 接收一个确定要进行的命令的数字和(可选地)另一个参数, 常常是一个指针. 作为一个使 用 /proc 文 ...
- CSS多余文本省略号显示
CSS多余文本省略号显示 本次案例代码是在 elementui 当中的 table 组件中实际需求 当然使用的是纯 CSS3 代码,所以原生支持度高,兼容性高,所以可多场景应用 对于过长文本进行单行省 ...
- 在eclipse动态网页项目中,编写web.xml时,servlet标签报错.
cvc-complex-type.2.4.b: The content of element 'servlet' is not complete. One of '{"http:// jav ...