使用 {merge: true} 设置 Firestore 和更新之间的区别
Difference Between Firestore Set with {merge: true} and Update
在 Cloud Firestore 中有三个写入操作:
add()
set()
update()
文档中说使用 set(object, { merge: true })
会将给定对象与现有文档合并。
当您使用 update(object)
时也会发生同样的情况...那有什么区别呢? google 会重复这样的功能似乎很奇怪。
我理解差异的方式:
set
没有 merge
将覆盖文档或创建文档(如果文档尚不存在)
set
和 merge
将更新文档中的字段或如果不存在则创建它
update
将更新字段,但如果文档不存在则会失败
create
将创建文档,但如果文档已存在则创建失败
您提供给 set
和 update
的数据类型也有所不同。
对于set
,您始终必须提供文档格式的数据:
set(
{a: {b: {c: true}}},
{merge: true}
)
通过 update
,您还可以使用字段路径来更新嵌套值:
update({
'a.b.c': true
})
"set with merge" 和 "update" 之间的另一个区别(扩展 Scarygami 的回答)是在使用嵌套值时。
如果您的文档结构如下:
{
"friends": {
"friend-uid-1": true,
"friend-uid-2": true,
}
}
并想添加 {"friend-uid-3" : true}
使用这个:
db.collection('users').doc('random-id').set({
"friends": {
"friend-uid-3": true
}
},{merge:true})
将产生以下数据:
{
"friends": {
"friend-uid-1": true,
"friend-uid-2": true,
"friend-uid-3": true
}
}
但是 update
使用这个:
db.collection('users').doc('random-id').update({
"friends": {
"friend-uid-3": true
}
})
将产生以下数据:
`{
"friends": {
"friend-uid-3": true
}
}`
根据文档:https://firebase.google.com/docs/firestore/manage-data/add-data#update_fields_in_nested_objects
点表示法允许您在不覆盖其他嵌套字段的情况下更新单个嵌套字段。如果您更新没有点符号的嵌套字段,您将覆盖整个地图字段。
如上所述,这会替换整个朋友结构。
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 创建虚拟文档。
可能的用例:将 google 分析合并到来自 analytics reporting api
的文档中,当此 api 同时提供现有文档和已删除文档的数据时.
进一步补充上述答案,如果您想要删除 地图中的嵌套字段,那么您可能想要使用update
或set
取决于您的用例。
如果您从以下内容开始并希望删除 "user1"
以外的所有配置文件条目,那么您有两个选择。
{
"users": {
"profiles": {
"user1": ...,
"user2": ...
}
}
更新
这将用提供的内容覆盖 profiles
update({
'users.profiles': { 'user1': ... }
})
设置
这会将删除的内容合并到现有配置文件中,
保留未删除的内容
set({
users: {
profiles: {
'user2': FieldValue.delete(),
'user3': FieldValue.delete(),
...
}
}
}, { merge: true })
这仅适用于 Map
,因为 set
和 update
都会覆盖数组,除非您明确使用 array-specific operators such as arrayUnion
.
在 Cloud Firestore 中有三个写入操作:
add()
set()
update()
文档中说使用 set(object, { merge: true })
会将给定对象与现有文档合并。
当您使用 update(object)
时也会发生同样的情况...那有什么区别呢? google 会重复这样的功能似乎很奇怪。
我理解差异的方式:
set
没有merge
将覆盖文档或创建文档(如果文档尚不存在)set
和merge
将更新文档中的字段或如果不存在则创建它update
将更新字段,但如果文档不存在则会失败create
将创建文档,但如果文档已存在则创建失败
您提供给 set
和 update
的数据类型也有所不同。
对于set
,您始终必须提供文档格式的数据:
set(
{a: {b: {c: true}}},
{merge: true}
)
通过 update
,您还可以使用字段路径来更新嵌套值:
update({
'a.b.c': true
})
"set with merge" 和 "update" 之间的另一个区别(扩展 Scarygami 的回答)是在使用嵌套值时。
如果您的文档结构如下:
{
"friends": {
"friend-uid-1": true,
"friend-uid-2": true,
}
}
并想添加 {"friend-uid-3" : true}
使用这个:
db.collection('users').doc('random-id').set({
"friends": {
"friend-uid-3": true
}
},{merge:true})
将产生以下数据:
{
"friends": {
"friend-uid-1": true,
"friend-uid-2": true,
"friend-uid-3": true
}
}
但是 update
使用这个:
db.collection('users').doc('random-id').update({
"friends": {
"friend-uid-3": true
}
})
将产生以下数据:
`{
"friends": {
"friend-uid-3": true
}
}`
根据文档:https://firebase.google.com/docs/firestore/manage-data/add-data#update_fields_in_nested_objects
点表示法允许您在不覆盖其他嵌套字段的情况下更新单个嵌套字段。如果您更新没有点符号的嵌套字段,您将覆盖整个地图字段。
如上所述,这会替换整个朋友结构。
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 创建虚拟文档。
可能的用例:将 google 分析合并到来自 analytics reporting api
的文档中,当此 api 同时提供现有文档和已删除文档的数据时.
进一步补充上述答案,如果您想要删除 地图中的嵌套字段,那么您可能想要使用update
或set
取决于您的用例。
如果您从以下内容开始并希望删除 "user1"
以外的所有配置文件条目,那么您有两个选择。
{
"users": {
"profiles": {
"user1": ...,
"user2": ...
}
}
更新
这将用提供的内容覆盖 profiles
update({
'users.profiles': { 'user1': ... }
})
设置
这会将删除的内容合并到现有配置文件中, 保留未删除的内容
set({
users: {
profiles: {
'user2': FieldValue.delete(),
'user3': FieldValue.delete(),
...
}
}
}, { merge: true })
这仅适用于 Map
,因为 set
和 update
都会覆盖数组,除非您明确使用 array-specific operators such as arrayUnion
.