Cloud Function无法在Firestore中创建/存储文档问题排查
问题描述
Cloud Function无法在Firestore中创建或存储文档。函数可正常读取Cloud Storage图片并调用Vision API识别出正确标签,但写入Firestore时触发5 NOT_FOUND错误,日志显示Firestore database ID为undefined。
函数代码
const { Firestore, Timestamp } = require('@google-cloud/firestore'); const { ImageAnnotatorClient } = require('@google-cloud/vision'); const client = new ImageAnnotatorClient(); const projectId = "*project-id*"; const databaseId = "*database-id*"; const db = new Firestore({ projectId, databaseId }); console.log('Firestore database client:', db); console.log("Firestore database ID: ", db.databaseId); exports.processImage = async (event, context) => { // 检查事件数据是否存在 if (!event || !event.name || !event.bucket) { console.error('无效的Cloud Storage事件,退出执行。'); return; } const filePath = event.name; const bucketName = event.bucket; const fileName = filePath.split('/').pop(); // 准备Vision API请求的图片地址 const imageUri = `gs://${bucketName}/${filePath}`; console.log(`调用Vision API处理图片: ${imageUri}`); // 调用Vision API try { const [result] = await client.labelDetection(imageUri); const labels = result.labelAnnotations.map(label => label.description); console.log(`识别到标签: ${labels.join(', ')}`); // 将标签存储到Firestore const docRef = db.collection('photo-ai-db').doc(fileName); console.log(`写入Firestore文档路径: ${docRef.path}`); try { // 使用merge选项创建或更新文档 await docRef.update({ labels, processedAt: Timestamp.now() }); await docRef.set({ labels, processedAt: Timestamp.now() }, { merge: true }); console.log(`图片${fileName}处理完成,标签已存储到Firestore。`); } catch (error) { console.error('写入Firestore失败:', error); } } catch (error) { console.error('调用Vision API失败:', error); } };
关键日志片段
DEFAULT 2024-03-27T05:18:24.393704Z Firestore database client: Firestore { DEFAULT 2024-03-27T05:18:24.393731Z _settings: { DEFAULT 2024-03-27T05:18:24.393739Z projectId: '*project-id*', DEFAULT 2024-03-27T05:18:24.393745Z databaseId: '*database-id*', ... DEFAULT 2024-03-27T05:18:24.394410Z Firestore database ID: undefined ... DEFAULT 2024-03-27T05:18:33.435653Z Error writing to Firestore: Error: 5 NOT_FOUND:
解决方案
1. 修正Firestore初始化逻辑
@google-cloud/firestore v4.x版本中,databaseId不会直接暴露为实例属性,日志中db.databaseId显示undefined属于正常现象,但初始化配置需注意:
- 若使用Firestore原生模式,默认数据库ID为
(default),无需手动指定,可简化初始化代码:// 自动从环境变量获取项目ID和默认数据库 const db = new Firestore(); - 若使用自定义数据库ID,需确保ID正确且目标数据库已在项目中创建。
2. 修复文档写入逻辑
代码中同时调用update和set是错误的:update要求文档必须存在,否则会抛出NOT_FOUND错误。只需保留set方法并启用merge选项,即可实现"不存在则创建,存在则更新"的效果:
// 移除多余的update调用 await docRef.set({ labels, processedAt: Timestamp.now() }, { merge: true });
3. 检查Cloud Function权限
确保Cloud Function的服务账号拥有Cloud Datastore User或Firestore Editor角色,允许写入Firestore数据。可在Google Cloud控制台IAM页面为服务账号添加对应权限。
4. 验证数据库与函数的区域一致性
确认Firestore数据库的部署区域与Cloud Function的运行区域一致,避免跨区域访问导致的连接问题。
内容的提问来源于stack exchange,提问作者Ahmed
相关产品推荐
相关产品推荐

