使用MongoDB,如何使用变量中的对象更新数组中的对象

With MongoDB, how do I update an object within in array with an object from a variable?

本文关键字:对象 更新 数组 变量 MongoDB 何使用 使用      更新时间:2023-09-26

我有一个分配给变量的对象,例如:

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

这也不起作用。我引用了这篇文章:用mongo查询通过id更新数组元素

以及: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,子id是我提到的对象。

我用孩子_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运行了所有的值,以确保我得到了它们。

所以你说的是你有一个这样的文档:

{
    "_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()这个字符串才能获得一个有效的对象。

这里的单个数组元素只是一个例子。这里重要的是查询中具有匹配元素的位置$运算符语法。单个数组元素或数百个数组元素没有区别。只要您只更新数组中的一个元素。