【问题标题】:With MongoDB, how do I update an object within in array with an object from a variable?使用 MongoDB,如何使用变量中的对象更新数组中的对象?
【发布时间】:2014-10-05 02:50:42
【问题描述】:

我有一个对象赋值给一个变量,比如:

var child = {
    { 
        _id: 'ObjectID("16e7f7baa05c3a9d751363")',
        title: 'Testing',
        sort: 3,
        active: true 
    }

以下内容不起作用,老实说,我不确定自己缺少什么:

db.category.update(
    { _id: "thisistheparentdocumentsid", "children._id": child._id },
    {
        $set: {
            "children.$.title": child.title,
            "children.$.active": child.active,
            "children.$.sort": child.sort
        }
    }
);

我真正想做的,因为我想重用这个方法,以后不再重复自己是:

db.category.update(
    { _id: "thisistheparentdocumentsid", "children._id": child._id },
    {
        $set: {
            "children" : child
        }
    }
);

这也不起作用。我引用了这篇文章:Update array element by id with mongo query

还有:http://docs.mongodb.org/manual/reference/operator/update/positional/

但我的查询不起作用。我在这里错过了一些基本的东西吗?

--- 编辑---

这是我根据父文档查询的结果

db.category.findOne({ "_id" : "9dYgKdfFczgiRcNouij"});
{
        "title" : "ParentTest",
        "active" : true,
        "children" : [
                {
                        "_id" : ObjectId("680d55c6995ef6f0748278c2"),
                        "title" : "ChildTest",
                        "active" : true
                                            },
                {
                        "_id" : ObjectId("2b4469c1a4c8e086942a1233"),
                        "title" : "ChildTest2"
                        "active" : true
                }
        ],
        "_id" : "9dYgKdfFczgiRcNouij"
}

我正在向服务器传递数据,例如... Method.call("UpdateCommand", id, child);

变量id是文档的父id,子是我提到的对象。

我使用 child._id.toString() 来生成匹配的 ObjectId("...");

更具体地说:

db.category.update(
        { _id: id, "children._id": child._id.toString() },
        {
            $set: {
                "children.$.title": child.title,
                "children.$.active": child.active,
                "children.$.sort": child.sort,
                "children.$.uppercase": child.title.toUpperCase()
            }
        }
    );

但这不起作用。我认为我的选择器有些问题,但我可以使用 findOne() 和相同的方法,它确实返回正确的文档,并且使用 $elemMatch 返回数组中指定的子项。

我可能遗漏了什么?我已经通过 console.log 运行了所有值,以确保我得到它们,而且我是。

【问题讨论】:

    标签: javascript mongodb mongodb-query


    【解决方案1】:

    所以你的意思是你有这样的文件:

    {
        "_id": ObjectId("5430b55d214047b8ee55d40b"),
        "children": [
            { 
                "_id": ObjectID("16e7f7baa05c3a9d751363"),
                "title": "Testing",
                "sort": 2,
                "active": false 
            }
        }
    }
    

    或类似的东西,但至少有很多这样的孩子。只要您乐意使用变量对象中的值更新“子”条目中的元素,那么这没有任何问题:

    db.category.update(
        { "_id": ObjectId("5430b55d214047b8ee55d40b"), "children._id": child._id },
        { "$set": { "children.$": child }
    )
    

    这将替换整个元素的位置。

    如果您担心替换整个内容,您可能会遇到这样的情况:

    {
        "_id": ObjectId("5430b55d214047b8ee55d40b"),
        "children": [
            { 
                "_id": ObjectID("16e7f7baa05c3a9d751363"),
                "title": "Testing",
                "sort": 2,
                "active": false,
                "created": ISODate("2014-10-03T03:09:20.609Z")
            }
        }
    }
    

    然后你可以处理对象的键来构造你的$set语句:

    var update = { "$set": {} };
    
    for ( var k in child ) {
        if ( k != "_id" )
            update["$set"]["children.$."+k] = child[k];
    }
    
    db.category.update(
        { "_id": ObjectId("5430b55d214047b8ee55d40b"), "children._id": child._id },
        update
    );
    

    它将在原地处理更新,但不会覆盖未提供的“已创建”字段。

    还要注意你在ObjectId 值周围的引号'',但我希望这只是一个错字,否则你需要eval() 字符串才能获得有效的对象。

    这里的单个数组元素只是示例。此处重要的是带有查询中匹配元素的 positional $ 运算符语法。单个数组元素或数百个元素没有区别。只要你只更新数组的一个元素。

    【讨论】:

    • 我刚刚在我的问题底部添加了更多细节,实际上是在您回答的同时。现在阅读您的答案,但如果您愿意查看我的更新?
    • @user1447679 已经看到了。数组中有多少元素并不重要。我自己的修订反映了这一点。如果你的 parentId 是一个字符串(奇怪的是你在这里混合了类型)那么它就是一个字符串。
    • 我在通过服务器上的更新方法发送之前记录子对象,它看起来像这样: Object {_id: "ObjectID("19636533c66b0fd89f72f4b1")", title: "Testing ", sort: 2, active: true} 将 ObjectID 用引号括起来似乎不正确吗?我想知道它是否作为字符串发送。
    • @user1447679 是的,用引号括起来是不正确的,因为这意味着它只是一个字符串。由于您的数据中实际上似乎有“真实”的 ObjectId 值,因此您需要使用 client._id = eval(client._id); 之类的东西处理字符串,以便将其转换为真实的 ObjectId 值。您首先应该真正研究一下是什么代码甚至将其生成为字符串。
    • 再次感谢您。我将您的答案标记为正确,因为它是正确的。似乎我遇到了与我正在使用的框架(MeteorJS)以及它当前如何处理传统 ObjectID 相关的一些其他问题。在尝试了你的最后一个建议后,我得到了 ReferenceError: ObjectID is not defined,这导致我这样做:stackoverflow.com/questions/11979403/… 我将继续处理这个问题,但这一定是问题所在。谢谢您...非常感谢您的不断评论和您的详细回答。您在答案中的详细信息非常有帮助
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-20
    • 2020-06-13
    • 2023-02-11
    • 2015-05-12
    • 2015-12-12
    • 1970-01-01
    • 2021-04-29
    相关资源
    最近更新 更多