概要

本文主要讲述在 mongodb 中,怎么更新嵌套数组的值。

使用$更新数组

  1. 基本语法  { "<array>.$" : value }
  2. 可以用于:update, findAndUpdate 等方法
  3. $是一个占位符一样的存在。代表被匹配的数组中的一个元素
  4. 可以匹配一个数组,匹配多个是会异常  index 0: 2 - Too many positional (i.e. '$') elements found in path ... ,即:只能在一层嵌套的数组中使用 $
  5. 示例 
    db.collection.update(
    { <array>: value ... },
    { <update operator>: { "<array>.$" : value } }
    )

测试

  1.     创建一个测试数据

    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);
    }

    创建数据脚本

    数据截图:

  2. 我想更新arr_1数组中,a = 1 的对象,更新为 {a:11,b:12} 运行更新代码,如下:
    db.nestedUpdate.updateMany({
    'arr_1.a': 1
    }, {
    $set: {
    'arr_1.$.a': 11,
    'arr_1.$.b': 12,
    }
    })

    运行后数据截图:

  3.   针对上述结构,更新 a= 11 的对象值(与上面不同,上面是更新对象里面的一个值),运行一下代码:
    db.nestedUpdate.updateMany({
    'arr_1.a': 11
    }, {
    $set: {
       'arr_1.$': {a:11, c:[1,2,3]}
    } })

    运行结果:

  4. 继续编辑,修改 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 (循环判断保存法)

  1. 通过 .find 找到满足条件的集合,(但只能找到根节点)
  2. 遍历需要修改的节点,修改其值,(先遍历arr_1, 在遍历 arr_1.c)
  3. 把修改完成的对象,通过 save 方法更新回数据库。
  4. 代码如下
    // 查找所有
    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> } ] }
)

注意

  • 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 更新嵌套数组的值的更多相关文章

  1. C# .NET Core 3.1中使用 MongoDB.Driver 更新嵌套数组元素和关联的一些坑

    C# .NET Core 3.1中使用 MongoDB.Driver 更新数组元素和关联的一些坑 前言: 由于工作的原因,使用的数据库由原来的 关系型数据库 MySQL.SQL Server 变成了 ...

  2. MongoDB按照嵌套数组中的map的某个key无法正常排序的问题

    前阵子同事有一个需求: 在一个数组嵌套map的结构中,首先按照map中的某个key进行筛选,再按照map中的某个key进行排序,但是奇怪的是数据总是乱序的. 再检查了代码和数据之后并没有发现什么错误, ...

  3. 【MongoDB】嵌套数组查询方案

    From:http://stackoverflow.com/questions/12629692/querying-an-array-of-arrays-in-mongodb 数据 db.multiA ...

  4. MongoDB学习笔记~官方驱动嵌套数组对象的更新

    回到目录 对于数组对象mongodb本身是支持的,不过对于数组的更新,mongodb的Csharp驱动目前只支持一级,即你的对象里包含数组,而数组又包括数组,这表示两层,这在更新子数组时,Csharp ...

  5. Vue 嵌套数组 数组更新视图不更新

    关于Vue的响应式原理,可以看官方文档或其他资料, https://www.jianshu.com/p/34de360d6035 data里定义了一个数组arr,数组的元素可以是同样格式的数组arrC ...

  6. .NET 云原生架构师训练营(模块二 基础巩固 MongoDB 更新和删除)--学习笔记

    2.5.4 MongoDB -- 更新和删除 整体更新 更新字段 字段操作 数组操作 删除 https://docs.mongodb.com/manual/reference/operator/upd ...

  7. [C#]想说一说嵌套数组

    今天早上,随感而发,随便写了点东西.结果下午的时候看了看评论,吓我一跳.估计是不是写代码的人看散文看得太少了,还是因为现在的人读的书太少了,似乎有有些大惊小怪. 关于Y美女,我声明一下,尽管她很脱俗, ...

  8. [jQ/PHP]使用JS数组储值的两种情况(提交PHP处理)

    ---------------------------------------------------------------------------------------------------- ...

  9. MongoDB——更新操作(Update)c#实现

    c#实现 Mongodb存储[文档局部更新] 如下: 递归更新字段  ,构建UpdateDefinition   /// <summary>   /// 构建更新操作定义   /// &l ...

随机推荐

  1. H3C 路由器单播IP包转发

  2. hdu 3339 In Action(迪杰斯特拉+01背包)

    In Action Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  3. 深入理解String、StringBuffer、StringBuilder(转)

    文章系转载,非原创,原地址: http://www.cnblogs.com/dolphin0520/p/3778589.html 相信String这个类是Java中使用得最频繁的类之一,并且又是各大公 ...

  4. CF1166E The LCMs Must be Large

    CF1166E The LCMs Must be Large 构造趣题 正着推其实很不好推 不妨大力猜结论 如果两两集合都有交,那么一定可以 证明: 1.显然如果两个集合没有交,一定不可以 2.否则给 ...

  5. Java 自带性能监控工具:监视和管理控制台 jconsole 的使用

    1. 前言想验证你对 jvm 配的一些调优参数(比如 Xms.Xmx 等)有没有起作用吗?想不想实时监控你自定义的线程池的在实际运行时的线程个数.有没有死锁?应用出现 java.lang.OutOfM ...

  6. P1095 水仙花数

    题目描述 春天是鲜花的季节,水仙花就是其中最迷人的代表,数学上有个水仙花数,他是这样定义的:"水仙花数"是指一个三位数,它的各位数字的立方和等于其本身,比如:153=1^3+5^3 ...

  7. Laravel5 call to undefined function openssl cipher iv length() 报错 PHP7开启OpenSSL扩展失败

    在安装laravel5.5后, 访问显示报错. call to undefined function openssl cipher iv length() 经查为php7.1的OpenSSL扩展加载失 ...

  8. P1043 查找小于x的最大元素

    题目描述 现在告诉你一个长度为 \(n\) 的有序数组 \(a_1, a_2, ..., a_n\) ,以及 \(q\) 次询问,每次询问会给你一个数 \(x\) ,对于每次询问,你需要输出数组 \( ...

  9. JVM调优-Jstack线程分析

    jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息,如果是在64位机器上,需要指定选项"-J-d64",Windows的jstack使 ...

  10. H3C 聚合链路负载分担原理