MongoDB - 更新嵌套数组中的对象

57
{
  "_id": "xPBc4By8FemDwTPqH",
  "u": {
    "_id": "6PoZawHZcQz4Gwzcv",
    "username": "michael"
  },
  "friends": [
    {
      "u": {
        "_id": "eGqDjAjjtYADbuSnn",
        "username": "michael",
        "name": "michael"
      }
    },
    {
      "u": {
        "_id": "k4gKCGwYryXDMMHvs",
        "username": "joyce",
        "name": "joyce"
      }
    }
  ]
}
我想更新“friends.u.username”的名字:“迈克尔”现在叫“你好”,我应该怎么做。

我想更新“friends.u.username”的名字:“迈克尔”现在叫“你好”,我应该怎么做。

4个回答

108
在您的更新中,使用$set运算符和$位置操作符一起来更改name字段。 $位置操作符将识别要更新的数组中的正确元素,而无需明确指定元素在数组中的位置,因此您的最终更新语句应如下所示:
db.collection.update(
    { "friends.u.username": "michael" }, 
    { "$set": { "friends.$.u.name": "hello" } }
)

如果要在多个元素与筛选器匹配时更新数组中的多个元素,可以使用 $\[<identifier>\] 语法和 arrayFilters 选项。以下代码将更新“friends”数组中所有匹配的元素:

db.collection.update(
    { "friends.u.username": "michael" },
    { "$set": { "friends.$[elem].u.name": "hello" } },
    { 
      "arrayFilters": [{ "elem.u.username": "michael" }], 
      "multi": true 
    }
)

$[elem] 语法标识符用于在 arrayFilters 选项中识别与指定筛选条件匹配的数组元素。添加 multi: true 选项以更新所有匹配的文档,而不仅是第一个。


1
由于某些原因,它对我不起作用... 什么也没有发生,但如果我使用 0 而不是 $,数组中的(错误)元素会更改。 - Dherik
@Dherik 你已经有一个关于你的问题的详细描述了吗?如果没有,你可以创建一个包含样例文档和期望结果的问题描述吗? - chridam
我会再试一下。也许是Robo3T和向后兼容性的某些驱动程序问题:https://dev59.com/Rm445IYBdhLWcg3w1tui#46054172。如果什么都不行,我会提出一个问题。谢谢! :) - Dherik
2
我正在使用MongoDB 3.2.0。显然,这个版本不支持这种操作。 - Dherik
2
对我来说,这只修改了一个元素。如果有多个元素匹配,则只会更新第一个。 - Mr.Cat
1
确实,这只会更新第一个匹配的嵌套元素。不知道如何允许多个匹配(更新)。 - yBother

8
您可以使用$set运算符。
> db.test.update({"friends.u._id":"eGqDjAjjtYADbuSnn"},{$set:{"friends.$.u.name":"hello"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

0
如果您正在使用Python,我创建了此函数以生成新的更新:
def generate_set_to_update_document(field: str, changes: dict) -> dict:
    new_set = {}
    for change in changes.keys():
        new_set[f"{field}.$.{change}"] = changes[change]
    return new_set

0

以下代码应该可以正常工作,因为已经测试过了

首先检查数组的当前值。

db.test.findOne({"friends.u.id" : "eGqDjAjjtYADbuSnn"},{"friends.u.name":1})

现在执行更新命令。
db.test.update({"friends.u.id" : "eGqDjAjjtYADbuSnn"},{$set:{"friends.$.u.name":"hello"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

现在再次检查结果以验证更新的值。
db.test.findOne({"friends.u.id" : "eGqDjAjjtYADbuSnn"},{"friends.u.name":1})

希望这能有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接