【问题标题】:Firebase function return batch of updates error Cannot modify a WriteBatch that has been committedFirebase 函数返回批量更新错误无法修改已提交的 WriteBatch
【发布时间】:2021-06-20 10:14:42
【问题描述】:

这是我的代码:

exports.updateUserName = functions.firestore
  .document("users/{userId}")
  .onUpdate((change, context) => {
    const newValue = change.after.data().name;
    const previousValue = change.before.data().name;
    const userID = context.params.userId;
    var batch = admin.firestore().batch();
    if (newValue != previousValue) {

      //Update author in sets/{set_id}/author
       admin
        .firestore()
        .collection("sets")
        .where("authorId", "==", userID)
        .get()
        .then((querySnapshot) => {
          if (!querySnapshot.empty) {
             querySnapshot.forEach((doc) => {
              batch.update(doc.ref,{ "author": newValue });
            });
          }
        }),

    //Update author in courses/{course_id}/author
      admin
        .firestore()
        .collection("courses")
        .where("authorId", "==", userID)
        .get()
        .then((querySnapshot) => {
          if (!querySnapshot.empty) {
             querySnapshot.forEach((doc) => {
              batch.update(doc.ref,{ "author": newValue });
            });
          }
        })
    }
   return batch.commit().then(() => {
    console.log("commited")
  });
  });

所以我想更新两个不同的文档。我想我必须用批处理()来做到这一点。 但我得到了错误:

Error: Cannot modify a WriteBatch that has been committed.
    at WriteBatch.verifyNotCommitted (/workspace/node_modules/@google-cloud/firestore/build/src/write-batch.js:117:19)
    at WriteBatch.update (/workspace/node_modules/@google-cloud/firestore/build/src/write-batch.js:313:14)
    at /workspace/index.js:84:21
    at QuerySnapshot.forEach (/workspace/node_modules/@google-cloud/firestore/build/src/reference.js:748:22)
    at /workspace/index.js:83:33
    at processTicksAndRejections (internal/process/task_queues.js:97:5)

这是我第一次使用批处理或必须使用一个云功能更新 2 个文档。 我做错了什么?

【问题讨论】:

    标签: javascript node.js firebase google-cloud-firestore google-cloud-functions


    【解决方案1】:

    在调用commit() 之前,您需要等待异步查询完成并填充批处理。为此,您需要 chain the promises 并在 Cloud Function 中返回此链。

    所以以下应该可以解决问题(未经测试):

    exports.updateUserName = functions.firestore
        .document("users/{userId}")
        .onUpdate((change, context) => {
            const newValue = change.after.data().name;
            const previousValue = change.before.data().name;
            const userID = context.params.userId;
            const db = admin.firestore();
            const batch = db.batch();
            if (newValue != previousValue) {
    
                //Update author in sets/{set_id}/author
                return db
                    .collection("sets")
                    .where("authorId", "==", userID)
                    .get()
                    .then((querySnapshot) => {
                        if (!querySnapshot.empty) {
                            querySnapshot.forEach((doc) => {
                                batch.update(doc.ref, { "author": newValue });
                            });
                        }
    
                        return db
                            .collection("courses")
                            .where("authorId", "==", userID)
                            .get();
                    })
                    .then((querySnapshot) => {
                        if (!querySnapshot.empty) {
                            querySnapshot.forEach((doc) => {
                                batch.update(doc.ref, { "author": newValue });
                            });
                        }
                        return batch.commit();
                    })
                    .then(() => {
                        console.log("commited")
                        return null;
                    });
            } else {
                return null;
            }
        });
    

    不要忘记批量写入有 500 个文档的限制。如果你知道你可能会超过这个限制,你可以改用Promise.all(),如下:

    exports.updateUserName = functions.firestore
        .document("users/{userId}")
        .onUpdate((change, context) => {
            const newValue = change.after.data().name;
            const previousValue = change.before.data().name;
            const userID = context.params.userId;
            const db = admin.firestore();
            var promises = [];
            
            if (newValue != previousValue) {
    
                //Update author in sets/{set_id}/author
                return db
                    .collection("sets")
                    .where("authorId", "==", userID)
                    .get()
                    .then((querySnapshot) => {
                        if (!querySnapshot.empty) {
                            querySnapshot.forEach((doc) => {
                                promises.push(doc.ref.update({ "author": newValue }));
                            });
                        }
                        return db
                            .collection("courses")
                            .where("authorId", "==", userID)
                            .get();
                    })
                    .then((querySnapshot) => {
                        if (!querySnapshot.empty) {
                            querySnapshot.forEach((doc) => {
                                promises.push(doc.ref.update({ "author": newValue }));
                            });
                        }
                        return Promise.all(promises);
                    })
                    .then(() => {
                        console.log("commited")
                        return null;
                    });
            } else {
                return null;
            }
        });
    

    最后,请注意这个更容易阅读的 async/await 版本:

    exports.updateUserName = functions.firestore
        .document("users/{userId}")
        .onUpdate(async (change, context) => {
            const newValue = change.after.data().name;
            const previousValue = change.before.data().name;
            const userID = context.params.userId;
            const db = admin.firestore();
            const batch = db.batch();
            if (newValue != previousValue) {
    
                let querySnapshot = await db
                    .collection("sets")
                    .where("authorId", "==", userID)
                    .get();
    
                if (!querySnapshot.empty) {
                    querySnapshot.forEach((doc) => {
                        batch.update(doc.ref, { "author": newValue });
                    });
                }
    
                querySnapshot = await db
                    .collection("courses")
                    .where("authorId", "==", userID)
    
                if (!querySnapshot.empty) {
                    querySnapshot.forEach((doc) => {
                        batch.update(doc.ref, { "author": newValue });
                    });
                }
    
                await batch.commit();
                console.log("commited")
                return null;
    
            } else {
                return null;
            }
        });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-18
      • 1970-01-01
      • 2021-07-27
      • 2022-11-26
      相关资源
      最近更新 更多