React应用中Firestore写入触发器无法更新stories_json文档排查
问题描述
在React应用中使用Firebase数据库,编写Firebase Cloud Functions函数,需求如下:
- 当
stories集合插入新文档时自动触发函数 - 函数执行逻辑:
- 获取新文档的
titleIt、titleEn、descriptionIt、descriptionEn属性 - 获取
stories_json集合中指定文档(该文档初始包含空数组json) - 将步骤1的属性组成对象推入数组
- 将更新后的数组写回
stories_json的该文档
- 获取新文档的
实际问题:每次向stories添加新文档,stories_json中的文档始终未更新,json数组保持为空。
以下是编写的函数代码:
exports.updateStoriesJson = functions.firestore .document("/stories/{storyId}") .onWrite(async (event) => { const storyData = event.after.data(); if (storyData) { const titleIt = storyData.params.titleIt; const titleEn = storyData.params.titleEn; const descriptionIt = storyData.params.descriptionIt; const descriptionEn = storyData.params.descriptionEn; const json = {titleIt, titleEn, descriptionIt, descriptionEn}; const jsdonDocCollection=admin.firestore().collection("stories_json"); const jsonDoc=jsdonDocCollection.doc("7GaNrl34utwq7C9lvHz4"); const docSnapshot = await firestore.get(jsonDoc); let jsonArray = docSnapshot.data().json; jsonArray.push(json); await jsonDoc.set({json: jsonArray}); } return; });
stories_json集合结构:包含一个文档,该文档拥有空数组属性json。
错误分析与修复方案
主要错误点
- 文档属性获取方式错误:
storyData是Firestore文档的直接数据对象,无需通过params访问属性,storyData.params本身不存在,导致所有属性变量为undefined,推入数组的是无效对象,甚至会引发后续执行错误。 - Firestore实例调用错误:代码中使用
firestore.get(jsonDoc),但正确的调用方式是借助admin.firestore()实例(前提是已正确初始化admin模块),否则会因找不到firestore对象导致函数执行失败。 - 未处理文档不存在的情况:如果
stories_json中的指定文档不存在,docSnapshot.data()会返回undefined,访问docSnapshot.data().json会直接抛出错误,导致函数中断,无法完成更新。 - 触发器选择不当:
onWrite触发器会在文档创建、更新、删除时均触发,可能导致重复执行或不必要的操作,应该使用onCreate触发器,仅在新文档插入时触发。
修复后的代码
// 确保已初始化admin模块 const admin = require('firebase-admin'); admin.initializeApp(); exports.updateStoriesJson = functions.firestore .document("/stories/{storyId}") .onCreate(async (snap) => { // 使用onCreate触发器,仅处理新文档插入场景 const storyData = snap.data(); if (!storyData) return; // 直接从文档数据中获取目标属性 const titleIt = storyData.titleIt; const titleEn = storyData.titleEn; const descriptionIt = storyData.descriptionIt; const descriptionEn = storyData.descriptionEn; const newItem = {titleIt, titleEn, descriptionIt, descriptionEn}; const jsonDocRef = admin.firestore().collection("stories_json").doc("7GaNrl34utwq7C9lvHz4"); const docSnapshot = await jsonDocRef.get(); let jsonArray = []; // 处理文档存在/不存在的情况,避免报错 if (docSnapshot.exists) { const docData = docSnapshot.data(); jsonArray = docData.json || []; // 兼容json字段未定义的场景 } jsonArray.push(newItem); // 使用merge: true,避免覆盖文档中可能存在的其他字段 await jsonDocRef.set({json: jsonArray}, {merge: true}); });
额外注意事项
- 确保函数已正确部署:执行
firebase deploy --only functions命令部署更新后的函数 - 查看函数日志:通过Firebase控制台的「函数」页面查看执行日志,排查是否存在其他隐性错误
- 原子性优化:若存在多文档同时插入的场景,建议使用Firebase事务(
runTransaction)避免数组更新冲突
内容的提问来源于stack exchange,提问作者Yanitsa Halacheva
相关产品推荐
相关产品推荐

