【问题标题】:Firebase Cloudstore: how to "update all"/"delete some" docs in a collection?Firebase Cloudstore:如何在集合中“更新所有”/“删除一些”文档?
【发布时间】:2018-01-15 16:13:01
【问题描述】:

对于上下文:我有一个 cron-job.org,它在我的 firebase 项目中触发 https 函数。

在这个函数中,我必须遍历集合中的所有文档并更新一个计数器(每个文档可能有不同的计数器值)。如果计数器达到限制,我将更新另一个集合(独立于第一个集合),并删除达到限制的文档条目。如果计数器没有超出限制,我只需使用更新后的计数器值更新文档条目。

我尝试改编文档中的示例,尝试使用事务、批处理,但我不确定如何继续。根据事务的描述,这是要走的路,但示例仅显示如何编辑单个文档。

这就是我所拥有的(尝试调整实时数据库样本):

function updateCounter() {
    var ref = db.collection('my_collection_of_counters');
    return ref.get().then(snapshot => {
        const updates = {};
        snapshot.forEach(child => {
            var docData = child.data();
            var newCounter = docData.counter+1;
            if (newCounter == 10) {
                // TO-DO: add to stock
                updates[child.key] = null;
            } else {
                docData.counter = newCounter;
                updates[child.key] = docData;   
            }
        });
        // execute all updates in one go and return the result to end the function
        return ref.update(updates);
    });
}

它不起作用,集合没有更新方法。更新集合中每个文档的最佳方法是什么?一个接一个?交易?有例子吗?

PS:updateCounter 是一个被 https 触发器调用的函数。 Cron+trigger 工作正常。

编辑 当一个项目达到阈值时,我想更新另一个集合,独立于计数器。嵌套事务是一个好的解决方案吗?

修改代码:

function updateCounter() {
    var ref = db.collection('my_collection_of_counters');
    var transaction = db.runTransaction(t => {
        return t.get(ref)
                .then(snapshot => {
                    let docs = snapshot.docs;
                    for (let doc of docs) {
                        var item = doc.data();
                        var newCounter = item.counter + 1;
                        if (newCounter == 10) {
                            console.log("Update my_stock");
                            // ADD item.quantity to stock collection
                        }else{
                            t.update(doc.ref, {counter: newCounter});
                        }
                    }
                });
    })
    .then(result => {
        console.log('Transaction success');
    })
    .catch(err => {
        console.log('Transaction failure:', err);
    });
}

【问题讨论】:

    标签: javascript firebase transactions google-cloud-firestore


    【解决方案1】:

    正如您自己已经注意到的,您需要在事务中执行此操作,以确保您可以在单个操作中更新当前计数器值。一旦您的计数器达到其阈值,您还可以在同一事务中创建新文档并删除现有文档。我认为在单个事务中对所有文档执行此操作没有任何好处,因为每个文档上的操作似乎与其他文档无关。

    在 Firestore 事务中,您 perform the operations on a Transaction object as shown in the documentation。在你的情况下,你会:

    1. 使用transaction.get()获取当前文档。
    2. 从文档中获取计数器。
    3. 增加计数器。
    4. 如果新值低于您的阈值:
      1. 调用transaction.update()将新的计数器值写入数据库
    5. 如果新值高于您的阈值:
      1. 在新集合上调用 transaction.create 以在其中创建文档。
      2. 在现有文档上调用transaction.delete,将其删除。

    更多信息,我建议扫描reference documentation for the Transaction class

    【讨论】:

    • 进步!我能够更新计数器集合中的每个文档。现在您的建议是根据我刚刚更新的元素的完成情况(即达到阈值)在另一个集合中创建一个元素。但是,我也想更新其他集合,而不是只创建一个新项目。当计数器达到阈值时,我想添加到现有的库存商品中。是否可以使用嵌套事务?这是一个好习惯吗?
    • 我不确定您是否可以嵌套事务,但无论如何都不应该需要它:您对库存的更新与读取现有计数器并更新/删除它的事务相同。跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-19
    • 1970-01-01
    • 1970-01-01
    • 2021-10-30
    • 1970-01-01
    • 2020-09-08
    相关资源
    最近更新 更多