使用{merge: true}设置的Firestore与更新之间的差异

云Firestore中有三个写操作:

  1. add()
  2. set()
  3. update()

在文档中,它说使用set(object, { merge: true })将合并给定对象与现有文档。

当你使用update(object)…那么有什么不同呢?谷歌会像这样复制功能,这似乎很奇怪。

96617 次浏览

我是这样理解的:

  • 没有mergeset将覆盖一个文档或创建一个文档(如果它还不存在)

  • setmerge将更新文档中的字段,如果它不存在,则创建它

  • update将更新字段,但如果文档不存在则会失败

  • create将创建文档,但如果文档已经存在,则创建失败

提供给setupdate的数据类型也有所不同。

对于set,你总是必须提供文档形状的数据:

set(
{a: {b: {c: true}}},
{merge: true}
)

update中,你还可以使用字段路径来更新嵌套值:

update({
'a.b.c': true
})

“用合并设置”和“更新”之间的另一个区别(扩展Scarygami的回答)是在处理嵌套值时。

如果你的文档结构是这样的:

 {
"friends": {
"friend-uid-1": true,
"friend-uid-2": true,
}
}

并且想要添加{"friend-uid-3" : true}

用这个:

< p > <代码> db.collection(“用户”). doc(“随机身份”)这里({ “朋友”:{ “friend-uid-3”:真的 } },{合并:真})< /代码> < / p >

将得到以下数据:

 {
"friends": {
"friend-uid-1": true,
"friend-uid-2": true,
"friend-uid-3": true
}
}

然而update使用这个:

< p > <代码> db.collection(“用户”). doc(随机身份).update ({ “朋友”:{ “friend-uid-3”:真的 } }) < /代码> < / p >

将得到以下数据:

 `{
"friends": {
"friend-uid-3": true
}
}`

每个docs: https://firebase.google.com/docs/firestore/manage-data/add-data#update_fields_in_nested_objects

点表示法允许您更新单个嵌套字段,而无需覆盖其他嵌套字段。如果更新一个没有点表示法的嵌套字段,则将覆盖整个map字段。

如上所述,这将取代整个好友结构。

db.collection('users').doc('random-id').update({
"friends": {
"friend-uid-3": true
}
})

但这不是。

db.collection('users').doc('random-id').update({
"friends.friend-uid-3": true
})

多一个有趣的行为,可能有用,但不明显。

当你更新batch,并且不想检查是否所有你试图更新存在的文档。

使用batch update,如果至少有一个文档不存在,则请求将失败。

使用batch set {merge: true},您的请求将成功更新所有现有文档,并为不存在的id创建虚拟文档。

可能的用例:从analytics reporting api将谷歌分析合并到您的文档中,当此api同时为现有和已删除的文档提供数据时。

进一步补充上面的答案,如果你在一个映射中想要删除嵌套字段,那么你可能想要使用updateset,这取决于你的用例。

如果您从以下开始,并希望删除除"user1"之外的所有配置文件条目,那么您有两个选项。

{
"users": {
"profiles": {
"user1": ...,
"user2": ...
}
}

更新

这将用所提供的内容覆盖profiles

update({
'users.profiles': { 'user1': ... }
})

这将合并删除到现有的配置文件, 保留未删除的内容

set({
users: {
profiles: {
'user2': FieldValue.delete(),
'user3': FieldValue.delete(),
...
}
}
}, { merge: true })

这只适用于__abc0,因为setupdate都会覆盖数组,除非显式地使用特定于数组的操作符,例如arrayUnion