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

IT技术 javascript arrays object firebase google-cloud-firestore
2021-02-09 06:08:37

我目前正在尝试 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() }] })

没有工作。这些查询会覆盖我的数组。

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

6个回答

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() 删除每个给定元素的所有实例。

@ArturCarvalho 不,在这段视频中解释了原因youtube.com/...
2021-03-22 06:08:37
如果有一种方法可以更新具有特定 id 的数组中的项目,那就太好了。像一个 arrayUnion 但有一个合并:true。目前它需要 2 个操作来删除数组项,然后使用新数据再次添加它。
2021-03-26 06:08:37
有没有办法更新数组中的特定索引?
2021-04-03 06:08:37
如何将此数组更新功能与“react-native-firebase”一起使用?(我在 react-native-firebase 的官方文档上找不到这个)
2021-04-06 06:08:37
对于需要在客户端执行此操作的人员,请使用“从‘firebase/app’导入 * 作为 firebase;” 然后“firebase.firestore.FieldValue.arrayUnion(NEW_ELEMENT)”
2021-04-10 06:08:37

2018 年 8 月 13 日编辑:现在支持 Cloud Firestore 中的原生数组操作。请参阅下面道格的回答


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

这段代码在这里:

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

这是说,在设置文件proprietary/docID,使得sharedWith = [{ 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在一次操作中获取文档和所有数据。

这太令人沮丧了……但谢谢你让我知道我不会发疯。
2021-03-22 06:08:37
这是一个很大的缺点,谷歌必须尽快修复它。
2021-03-30 06:08:37
@DougGalante 的回答表明这已得到修复。使用arrayUnion方法。
2021-04-01 06:08:37

这是 Firestore 文档中的最新示例:

firebase.firestore.FieldValue。阵列联合

var washingtonRef = db.collection("cities").doc("DC");

// Atomically add a new region to the "regions" array field.
washingtonRef.update({
    regions: firebase.firestore.FieldValue.arrayUnion("greater_virginia")
});

// Atomically remove a region from the "regions" array field.
washingtonRef.update({
    regions: firebase.firestore.FieldValue.arrayRemove("east_coast")
});
@nifCody,这确实会向现有数组“区域”添加一个新的字符串元素“greater_virginia”。我已经成功测试了它,绝对没有添加“对象”。它与所述问题同步:“推送新记录”。
2021-03-30 06:08:37

您可以使用事务(https://firebase.google.com/docs/firestore/manage-data/transactions)来获取数组,推送到它,然后更新文档:

    const booking = { some: "data" };
    const userRef = this.db.collection("users").doc(userId);

    this.db.runTransaction(transaction => {
        // This code may get re-run multiple times if there are conflicts.
        return transaction.get(userRef).then(doc => {
            if (!doc.data().bookings) {
                transaction.set({
                    bookings: [booking]
                });
            } else {
                const bookings = doc.data().bookings;
                bookings.push(booking);
                transaction.update(userRef, { bookings: bookings });
            }
        });
    }).then(function () {
        console.log("Transaction successfully committed!");
    }).catch(function (error) {
        console.log("Transaction failed: ", error);
    });
在 if 语句中,您应该将其更改为这个,因为您缺少如下所示documentReference添加userReftransaction.set(userRef, { bookings: [booking] });
2021-03-13 06:08:37
这将重新写入整个数组
2021-03-21 06:08:37

抱歉,聚会迟到了,但 Firestore 早在 2018 年 8 月就解决了,所以如果您仍在寻找它,那么所有关于数组的问题都已解决。

https://firebase.googleblog.com/2018/08/better-arrays-in-cloud-firestore.html官方博文

array-contains、arrayRemove、arrayUnion 用于检查、删除和更新数组。希望能帮助到你。