这是我的代码:
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 个文档。 我做错了什么?
答案 0 :(得分:1)
在调用 commit()
之前,您需要等待异步查询完成并填充批处理。为此,您需要 chain the promises 并在 Cloud 函数中返回此链。
所以以下应该可以解决问题(未经测试):
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;
}
});