【问题标题】:mongo forEach unable to update array in documentmongo forEach 无法更新文档中的数组
【发布时间】:2019-09-20 20:52:33
【问题描述】:

我正在尝试编写一个在 RoboMongo 中运行的 mongo 脚本,它将遍历集合中的所有文档。每个文档都包含一个数组myArray。文件如下所示:

{
  "name": "myApp",
  "myArray": [
    { "env": "dev", "dbHost": "db2dev.local" },
    { "env": "prod",  "dbHost": "db1prod.local" }
  ]

我想将 dev 中定义的 dbHost 字段复制到 prod。所以上面的结果是:

{
  "name": "myApp",
  "myArray": [
    { "env": "dev", "dbHost": "db2dev.local" },
    { "env": "prod",  "dbHost": "db2dev.local" }
  ]

当我尝试访问 myArray[0] 字段时,我收到一个语法错误,上面写着:

TypeError: myDoc.myArray[0] is undefined

函数是这样的:

db.myCollection.find().forEach( function(myDoc) {
    var devIdx = 0;
    var prodIdx = 1;
    if (myDoc.myArray[0].env !== 'dev')}
        devIdx = 1;
        prodIdx = 0;
    }
    myDoc.myArray[prodIdx].dbHost = myDoc.myArray[devIdx].dbHost;

    print(myDoc);
});

我检查了集合(它非常小),每个文档都有一个 myArray 字段,因为它应该在数组中有两个值(一个用于dev,一个用于prod)。

我做错了什么?在 mongo 脚本中使用的正确语法是什么?不支持更新文档中的数组吗?

寻找解决方案

我已经搜索并找到了 forEach 示例,但大多数都是微不足道的,没有一个包含正在访问或更改的数组。

mongo 文档也非常简单:https://docs.mongodb.com/v3.6/reference/method/cursor.forEach/

【问题讨论】:

  • 你能告诉我们你在 myDoc 中得到了什么吗?
  • 脚本没有运行,所以我得到一个语法错误。我正在追踪它,并在 SO 上找到了另一个对我有帮助的解决方案。我正在学习 Mongo 不支持像普通 javascript 那样访问数组中的项目。当我弄清楚时,我会发布一个答案。如果我只有一个forEach(function(myDoc) { print(myDoc) });,那么我会得到输入文档。
  • 嘿,我实际上在文档中的一个数组上做了一个 for 循环,并修改了其中的对象。我不认为mongo不允许这样做。
  • 你能否像我的问题一样让非循环工作myArray[0]?只是好奇。我已经使用循环重新编写并让它工作,我现在正在研究如何在循环期间更新文档。
  • 我没有看到非循环行为。但我认为它在 for 循环中工作,那么它也应该在非循环行为中工作。我希望您尝试像这样访问数组 myDoc['myArray'][0]

标签: mongodb


【解决方案1】:

Mongo javascript 不允许您像尝试那样直接访问数组(除非您处于 for 循环中)。所以解决方案如下:

db.myCollection.find({}).forEach( function(myDoc) {
    var foundDevEntry = null;
    var updatedProdEntry = false;

    // First time loop to get a copy of the dev entry
    for (var idx in myDoc.myArray) {
        if (myDoc.myArray[idx].env === 'dev') {
            foundDevEntry = myDoc.myArray[idx];
        }
    }

    // 2nd time loop to update the value
    for (var idx in myDoc.myArray) {
        if (myDoc.myArray[idx].env === 'prod') {
            myDoc.myArray[idx].dbHost = foundDevEntry.dbHost;
        }
    }

    // Now update the database with this change
    db.myCollection.update({_id: myDoc._id}, {$set: {"myArray": myDoc.myArray}});

    print(myDoc);   // So results are also returned when query is run
});

我已经去掉了错误检查以专注于所需的更改。 (对我来说)奇怪的是语法 myDoc.myArray[idx] 实际上是有效的,但只在循环内!

以下参考资料帮助我找到了解决方案:

我应该补充一点,我读到的一些解决方案说要更新数组,您必须重新构建数组 (https://stackoverflow.com/a/22657219/3281336)。我在我的解决方案中没有这样做,它确实有效,但想分享它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-28
    • 2019-08-02
    • 1970-01-01
    • 2021-07-20
    • 1970-01-01
    • 2019-07-04
    • 2021-04-08
    相关资源
    最近更新 更多