Firestore子集合如何获取父文档ID?含云函数与安全规则问题
Firestore子集合获取父文档ID及对应安全规则实现
1. 云函数写入时获取父文档ID
原代码的核心问题是两次调用文档生成逻辑会产生独立的随机ID:第一次调用add()创建bot文档后没有保存返回的文档引用,第二次调用db.collection("bots").doc()会生成一个全新的、和之前创建的bot无关的文档引用,无法拿到正确的父ID。
修正后的代码直接保存add()返回的文档引用,从引用上直接取ID即可:
try { // 保存新建bot文档的引用 const botDocRef = await db.collection("bots").add({ createdBy: uid, createdAt: new Date(), }); // 基于已有的bot文档引用操作子集合 await botDocRef.collection("order_history").add({ createdBy: uid, botId: botDocRef.id, // 直接从引用上读取父文档ID }) } catch (e) { console.error("写入异常", e); // 自定义错误处理逻辑 }
如果是查询子集合文档时反向获取父ID,直接从文档快照的引用路径取值即可:snapshot.ref.parent.parent.id,其中第一个parent指向当前子集合的引用,第二个parent才是父级bot文档的引用。
2. 匹配父文档ID的安全规则写法
原规则存在三个问题:
- 条件之间缺少
&&逻辑运算符,语法不合法 - 规则中写的
id是order_history下当前文档的ID,不是父级bot文档的ID,匹配逻辑完全错误 - 直接依赖用户传入的
botId字段校验存在伪造风险,可直接从请求路径提取父ID做比对
固定路径匹配(推荐)
如果你的集合结构固定为bots/{botId}/order_history/{historyId},直接用精确路径匹配,性能更好、安全性更高:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /bots/{botId}/order_history/{historyId} { allow read, write: if request.auth != null // 校验传入的botId和路径上的父文档ID一致 && request.resource.data.botId == botId // 可选:额外校验创建者为当前登录用户,避免越权 && request.resource.data.createdBy == request.auth.uid; } } }
递归通配匹配
如果子集合可能存在于多层嵌套路径下,用递归通配时可通过路径片段提取父ID:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /{path=**}/order_history/{historyId} { allow read, write: if request.auth != null // 路径倒数第三个片段为父bot文档ID(路径结构:[...前缀, botId, "order_history", historyId]) && request.resource.data.botId == request.resource.ref.path[-3] && request.resource.data.createdBy == request.auth.uid; } } }
内容的提问来源于stack exchange,提问作者Fyl
相关产品推荐
相关产品推荐

