Firestore安全规则:如何检查数组对象中是否存在指定值?
Firestore安全规则与数据存储疑问
我的Firestore用户文档数据结构如下:
{ name: "Tom", groups: [ { groupId: "12345", moreInfo: "bla" }, { groupId: "67890", moreInfo: "bla" } ] }
我希望通过Firestore安全规则限制该文档的读写权限,仅当指定的groupId存在于groups数组中时允许访问。目前我写了规则的大致框架,但不知道如何完成数组对象的判断:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /users/{docId} { allow read, write: if "12345" in resource.data.groups.???; } } }
我有两个疑问:
- 能否不指定数组索引,直接检查数组内对象的
groupId值?目前没找到对应的内置函数。 - 是否需要通过创建子集合或独立文档来规范化存储用户与群组的关系?不确定哪种方案更优。
解答
1. 安全规则中直接检查数组对象的groupId
可以实现,不需要指定数组索引。Firestore安全规则支持使用map()方法遍历数组,提取每个对象的groupId字段生成纯ID数组,再用in操作符判断目标ID是否存在。修改后的规则如下:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /users/{docId} { allow read, write: if "12345" in resource.data.groups.map(group => group.groupId); } } }
map(group => group.groupId)会将groups数组中的每个对象转换为对应的groupId值,生成类似["12345", "67890"]的数组,之后就能直接用in判断目标ID是否在其中。
2. 是否需要规范化存储关系?
需根据业务场景判断:
- 当前嵌套数组方案适用场景:如果
groups数组不会频繁增删,且moreInfo这类附加信息需要和用户文档强绑定,当前方案完全可行,安全规则也能满足需求,无需额外调整。 - 规范化存储的适用场景:如果需要频繁对用户的群组进行增删操作、或需要单独查询某个群组下的所有用户、某个用户的所有群组,建议采用规范化方案:
- 子集合方案:在
users/{docId}下创建userGroups子集合,每个文档对应一个群组记录(包含groupId和moreInfo),安全规则可通过检查子集合中是否存在对应groupId的文档来控制权限。 - 关系文档方案:创建独立的
userGroupRelations集合,每个文档存储userId与groupId的关联关系,查询和权限校验都基于这个集合进行。
- 子集合方案:在
规范化存储的优势是能提升复杂查询的性能,避免嵌套数组过大导致文档体积超限,但会增加数据操作的复杂度,需根据业务需求权衡选择。
内容的提问来源于stack exchange,提问作者Tom Banister
相关产品推荐
相关产品推荐

