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

Zuz*_*zEL 73 database firebase google-cloud-firestore

Cloud Firestore中,有三种写操作:

1)添加

2)设置

3)更新

在文档中,它表示使用set(object, {merge: true})将对象与现有对象合并.

当你使用时会发生同样的情况update(object) 那么有什么不同呢?谷歌会复制逻辑似乎很奇怪.

Sca*_*ami 154

我理解差异的方式:

  • set 没有合并将覆盖文档或创建它(如果它还不存在)

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

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

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

您提供给set和的数据类型也有所不同update.

因为set你总是需要提供文件形状的数据:

set(
  {a: {b: {c: true}}},
  {merge: true}
)
Run Code Online (Sandbox Code Playgroud)

随着update你也可以使用现场路径用于更新嵌套值:

update({
  'a.b.c': true
})
Run Code Online (Sandbox Code Playgroud)

  • 您可以提到的另一个区别是`set`对文档形状的数据进行操作,其中`update`采用字段路径和值对.这意味着您可以使用`update`更改深度嵌套的值,这对`set`来说更麻烦.例如:`set({a:{b:{c:true}}},{merge:true})`vs`update('abc',true)`. (5认同)
  • 但是你在哪里找到 API 中的 `create` 方法? (3认同)
  • 无论如何设置合并选项都会覆盖该字段。但是,如果这不是最后一次更新,则更新将被忽略。例如,如果您在离线设备上触发更新操作,并在 3 天后恢复在线。 (3认同)
  • https://cloud.google.com/nodejs/docs/reference/firestore/0.8.x/DocumentReference#create 用于 node.js。Web API 似乎没有这种方法。不确定您在哪个平台上:) (2认同)

Fin*_*rcy 50

"使用合并"和"更新"之间的另一个区别(扩展Scarygami的答案)是使用嵌套值时.

如果您的文档结构如下:

 {
   "friends": {
     "friend-uid-1": true,
     "friend-uid-2": true,
   }
 }
Run Code Online (Sandbox Code Playgroud)

并想要添加 {"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
   }
 }
Run Code Online (Sandbox Code Playgroud)

然而update使用这个:

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

将导致此数据:

 `{
   "friends": {
     "friend-uid-3": true
   }
 }`
Run Code Online (Sandbox Code Playgroud)

  • 为了避免在使用“update”时覆盖嵌套字段中的数据(如上面的答案),您可以使用[点符号](https://firebase.google.com/docs/firestore/manage-data/add-data# update_fields_in_nested_objects)。如果您使用/不使用点表示法,“update”的覆盖行为会有所不同。 (5认同)
  • 我想到了.我以前只用数组试过这个.我想在数组中添加一个对象,并为该数组覆盖了所有内容.它不适用于包含数组的字段......它确实代表它的文档. (2认同)
  • 测试后得出相同的结论。我希望他们能够在更新函数中添加一个与“{ merge: true }”具有相同效果的选项。 (2认同)

小智 10

每个文档: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
    }
})
Run Code Online (Sandbox Code Playgroud)

这不。

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


geg*_*geg 7

进一步补充上面的答案,如果您想删除地图中的嵌套字段,那么您可能需要使用update或 ,set具体取决于您的用例。

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

{
  "users": {
    "profiles": {
      "user1": ...,
      "user2": ...
    }
  }
Run Code Online (Sandbox Code Playgroud)

更新

这将profiles用提供的任何内容覆盖

update({
  'users.profiles': { 'user1': ... }
})
Run Code Online (Sandbox Code Playgroud)

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

set({
  users: {
    profiles: {
      'user2': FieldValue.delete(),
      'user3': FieldValue.delete(),
      ...
    }
  }
}, { merge: true })
Run Code Online (Sandbox Code Playgroud)

这仅适用于Maps,因为setupdate都会覆盖数组,除非您显式使用特定于数组的运算符,例如arrayUnion