mongodb更新嵌套数组的值

database

概要

本文主要讲述在 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> } ] }

)

    • 官方文档地址: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

    View 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

回到顶部