Firestore 更新与合并 - 如何覆盖文档的一部分

Esb*_*ald 5 javascript firebase google-cloud-platform google-cloud-firestore

在 Firestore 中更新文档时,我想保留文档的大部分内容,但更改包含对象的一个​​属性。

我拥有的

{
  name: "John Doe",
  email: "me@example.com",
  friends: {
     a: {...},
     b: {...},
     c: {...},
     d: {...},
     e: {...},
     f: {...},
  }
}
Run Code Online (Sandbox Code Playgroud)

现在,我有一个新的朋友对象,例如{x: ..., y: ..., z: ...}

我想覆盖friends文档树,但保留所有其他字段。

我想要它的样子

{
  name: "John Doe",
  email: "me@example.com",
  friends: {
     x: {...},
     y: {...},
     z: {...},
  }
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我做一个firestore.doc(...).update({friends: {...}}, { merge: true })

我目前得到的

{
  name: "John Doe",
  email: "me@example.com",
  friends: {
     a: {...},
     b: {...},
     c: {...},
     d: {...},
     e: {...},
     f: {...},
     x: {...},
     y: {...},
     z: {...},
  }
}
Run Code Online (Sandbox Code Playgroud)

我知道我可以做两次更新,即删除字段然后再次设置它,或者我可以读取文档,更改对象并保存它而不合并。

但是,是否有一种聪明的方法可以覆盖对象(地图),同时保持文档的其余部分不变?

Ren*_*nec 6

由于您正在使用该update()方法,因此您只需在不使用合并选项的情况下调用它即可。

firestore.doc(...).update({friends: {...}})
Run Code Online (Sandbox Code Playgroud)

请注意,update()有两个不同的签名:

update(data: UpdateData)
Run Code Online (Sandbox Code Playgroud)

update(field: string | FieldPath, value: any, ...moreFieldsAndValues: any[])
Run Code Online (Sandbox Code Playgroud)

如果传递给该方法的第一个参数是一个对象,它将认为您使用第一个签名,因此只能传递一个参数。这样做

firestore.doc(...).update({friends: {...}}, { merge: true })
Run Code Online (Sandbox Code Playgroud)

应生成以下错误:

错误:函数 DocumentReference.update() 需要 1 个参数,但使用 2 个参数调用。


另一方面,你可以这样称呼它:

  firestore
    .collection('...')
    .doc('...')
    .update(
      'friends.c',
      'Tom',
      'email', 
      'mynew_email@example.com',
      'lastUpdate',
      firebase.firestore.FieldValue.serverTimestamp()
    );
Run Code Online (Sandbox Code Playgroud)

最后,为了完整起见,请注意如果您执行以下操作(传递一个字符串)

  firestore
    .collection('...')
    .doc('...')
    .update(
      'a_string'
    );
Run Code Online (Sandbox Code Playgroud)

你会得到以下错误

错误:函数 DocumentReference.update() 需要至少 2 个参数,但使用 1 个参数调用。

这是有道理的:-)

  • 谢谢 - 不知怎的,我没有注意到可以更新对象的特定字段,这很有意义,所以如果我将字段路径作为第一个参数,并且只覆盖文档的该部分。我还认为我对“update”和“set”方法有点困惑所以我想,当我需要合并时,我会调用“set(.... {merge:true{})”,当我需要覆盖一个特定字段,我将其称为“update("friends", {...})” (2认同)