部分更新覆盖MongoDB和FastAPI中的嵌套字段



我有这个模式

{
"_id": "5060ad4b-fb4a-4a34-b44a-32e97626dc0a",
"isDeleted": false,
"user": {
"timestamp": "2022-10-29",
"name": "john2",
"surname": "doe2",
"email": "12345@abcd.edu.tr",
"phone": "+012345678912",
"age": 20,
"gender": "male",
"nationality": "smth",
"universityMajor": "ENGINEERING",
"preferences": {
"doesMindHavingPets": true,
"isSmoker" : null,
"isMorning" : false
},
"password": "f61a20da9eaa68a9f06dbc1710b10ef0a67208b2059b1f576af6deac23c215f5"
},
(Other stuff)
.
.
.
.
}

我想做的是从客户端接收一个部分更新请求,它可能看起来像这样:

{
"email" : "12345@abcd.edu.tr",
"password" : "asdfghj",
"preferences" : {
"isSmoker" : true,
"doesMindHavingPets" : false
}
}

因此,我们可以使用嵌套字段首选项或不使用。

我想要的是合并文档,即更新电子邮件、密码和首选项。";外部";字段更新得很好,问题是首选项中的字段会被覆盖

例如:

使用过去的请求,文档将如下所示:

{
"_id": "5060ad4b-fb4a-4a34-b44a-32e97626dc0a",
"isDeleted": false,
"user": {
"timestamp": "2022-10-29",
"name": "john2",
"surname": "doe2",
"email": "12345@abcd.edu.tr",
"phone": "+012345678912",
"age": 20,
"gender": "male",
"nationality": "smth",
"universityMajor": "ENGINEERING",
"preferences": {
"doesMindHavingPets": false,
"isSmoker" : true,
"isMorning" : null
},
"password": "f61a20da9eaa68a9f06dbc1710b10ef0a67208b2059b1f576af6deac23c215f5"
}
}

因此isMorning字段被覆盖。我想要的输出是:

{
"_id": "5060ad4b-fb4a-4a34-b44a-32e97626dc0a",
"isDeleted": false,
"user": {
"timestamp": "2022-10-29",
"name": "john2",
"surname": "doe2",
"email": "12345@abcd.edu.tr",
"phone": "+012345678912",
"age": 20,
"gender": "male",
"nationality": "smth",
"universityMajor": "ENGINEERING",
"preferences": {
"doesMindHavingPets": false,
"isSmoker" : true,
"isMorning" : false
},
"password": "f61a20da9eaa68a9f06dbc1710b10ef0a67208b2059b1f576af6deac23c215f5"
}
}

我的当前查询更新了";外部";字段是这样的:

update_result = await dbConnection.find_one_and_update({"_id": id}, 
[ { "$set": { "user": { "$mergeObjects": [ "$user", new_user ] } }  } ], 
return_document = ReturnDocument.AFTER))

new_user这里是接收到的输入的字典,对于上面的JSON请求,new_user看起来像这样:

{'email': '12345@abcd.edu.tr', 'password': 'asdfghj', 'preferences': {'isSmoker': True, 'doesMindHavingPets': False}}

p.S:我正在使用FastAPI

如果有任何帮助,我将不胜感激:(

一个简单的选项是将其划分为嵌套和非嵌套阶段:

db.collection.find_one_and_update(
{_id: id},
[
{$set: {
"user.preferences": {$mergeObjects: ["$user.preferences", new_user.preferences]}
}},
{$set: {
user: {$mergeObjects: ["$user", new_user_first_layer]}
}}
])

看看它是如何在操场上工作的例子

最新更新