如何使用 Firestore 更新“对象数组”?

我目前正在尝试Firestore,我被困在一些非常简单的事情上:“更新数组(又名子文档)”。

我的数据库结构非常简单。例如:

proprietary: "John Doe",
sharedWith:
  [
    {who: "first@test.com", when:timestamp},
    {who: "another@test.com", when:timestamp},
  ],

我正在尝试(但没有成功)将新记录推送到对象数组中。shareWith

我试过了:

// With SET
firebase.firestore()
.collection('proprietary')
.doc(docID)
.set(
  { sharedWith: [{ who: "third@test.com", when: new Date() }] },
  { merge: true }
)

// With UPDATE
firebase.firestore()
.collection('proprietary')
.doc(docID)
.update({ sharedWith: [{ who: "third@test.com", when: new Date() }] })

均不起作用。这些查询将覆盖我的数组。

答案可能很简单,但我找不到它...


答案 1

Firestore现在有两个函数,允许您更新数组而无需重写整个内容。

链接:https://firebase.google.com/docs/firestore/manage-data/add-data,特别是 https://firebase.google.com/docs/firestore/manage-data/add-data#update_elements_in_an_array

更新数组中的元素

如果文档包含数组字段,则可以使用 arrayUnion() 和 arrayRemove() 来添加和删除元素。arrayUnion() 将元素添加到数组中,但仅添加尚不存在的元素。arrayRemove() 删除每个给定元素的所有实例。


答案 2

编辑 08/13/2018:Cloud Firestore 中现在支持本机阵列操作。请参阅下面的道格的答案


目前无法在 Cloud Firestore 中更新单个数组元素(或添加/删除单个元素)。

此代码在此处:

firebase.firestore()
.collection('proprietary')
.doc(docID)
.set(
  { sharedWith: [{ who: "third@test.com", when: new Date() }] },
  { merge: true }
)

这表示将文档设置为这样,但不影响任何现有文档属性。它与您提供的调用非常相似,但是,如果调用失败时文档不存在,则使用创建文档的调用。proprietary/docIDsharedWith = [{ who: "third@test.com", when: new Date() }update()set()update()

因此,您有两种选择来实现您想要的目标。

选项 1 - 设置整个阵列

使用数组的全部内容进行调用,这将需要首先从数据库中读取当前数据。如果您担心并发更新,则可以在事务中完成所有这些操作。set()

选项 2 - 使用子集合

您可以创建主文档的子集合。然后添加单个项目将如下所示:sharedWith

firebase.firestore()
  .collection('proprietary')
  .doc(docID)
  .collection('sharedWith')
  .add({ who: "third@test.com", when: new Date() })

当然,这带来了新的限制。您将无法根据文档的共享对象来查询文档,也无法在单个操作中获取文档和所有数据。sharedWith