【问题标题】:How does resource.data.size() work in firestore rules (what is being counted)?resource.data.size() 如何在 Firestore 规则中工作(计算什么)?
【发布时间】:2026-01-27 19:20:07
【问题描述】:

TLDR:在将一些布尔值和嵌套对象写入文档时,firestore 规则中的 request.resource.data.size() 计数是多少?不确定文档中“entries in the map”(https://firebase.google.com/docs/reference/rules/rules.firestore.Resource#datahttps://firebase.google.com/docs/reference/rules/rules.Map)是什么意思,在规则模拟器中测试时我的假设似乎是错误的(request.resource.data.keys().size() 的类似问题) .


加长版:在 Firestore 规则中遇到问题,无法按预期更新数据(尽管在规则模拟器中进行了类似的测试)。已将问题范围缩小到可以看到它是检查 request.resource.data.size() 是否等于某个数字的规则。

传递给 firestore update 函数的数据示例如下所示

 Object {
   "parentObj": Object {
     "nestedObj": Object {
       "key1": Timestamp {
         "nanoseconds": 998000000,
         "seconds": 1536498767,
       },
     },
   },
   "otherKey": true,
 }

时间戳是通过firebase.firestore.Timestamp.now() 生成的。 这在规则模拟器中似乎可以正常工作,但在执行时却不适用于实际数据

let obj = {}
obj.otherKey = true
// since want to set object key name dynamically as nestedObj value,
// see https://*.com/a/47296152/8236733
obj.parentObj = {} // needed for adding nested dynamic keys
obj.parentObj[nestedObj] = {
    key1: fb.firestore.Timestamp.now()
}

firebase.firestore.collection('mycollection')
.doc('mydoc')
.update(obj)

在其他一些规则中,我使用了规则request.resource.data.size() == 2,这似乎是导致权限被拒绝错误的规则(因为注释掉这个规则可以让事情再次运行)。会认为,由于对象是使用 2 个(*)键传递的,所以 request.resource.data.size()=2,但这显然不是这种情况(也不是传递对象中的键总数)(类似的问题request.resource.data.keys().size())。因此,对于一个简短的问题,有一个很长的例子。如果有人可以为我澄清这里出了什么问题,那将非常有帮助。

【问题讨论】:

    标签: google-cloud-firestore firebase-security


    【解决方案1】:

    从我大约一个月前与 Firebase 支持的最后一次沟通来看,request.resource.data.size() 和基于时间戳的查询安全规则存在问题。

    我还被告知request.resource.data.size() 是成功写入后文档的大小。因此,如果您要在具有 4 个键的文档中写入 2 个附加键,那么您应该检查的值是 6,而不是 2。

    说了这么多-我仍然对request.resource.data.size() 和任何替代品(例如似乎在本文档中使用的request.resource.size())有疑问 https://firebase.google.com/docs/firestore/solutions/role-based-access

    我的安全规则中也有一些地方似乎可以使用。我个人不知道为什么会这样。

    【讨论】:

    • 您是否知道任何其他方法来检查数据是否包含某些键(例如,我希望检查data.keys().hasAll(['expectedKey']) && data.size() == 1)?
    • 我不知道。理想情况下,我希望他们只添加类似 hasOnly() 的东西。如果您设法弄清楚需要什么才能使数据大小正常工作,请报告。
    • @jimmont 终于!
    • 为了后代,你想要request.resource.data.keys().hasOnly(['userId', 'anotherField'])
    【解决方案2】:

    为此苦苦挣扎了几个小时,我现在看到 Firebase 上的文档很清楚:“request.resource 变量包含文档的未来状态”。因此,对于所有字段,不仅是发送的字段。 https://firebase.google.com/docs/firestore/security/rules-conditions#data_validation.

    但实际上还有另一种方法可以只计算使用 request.writeFields.size() 发送的字段数。属性 writeFields 是一个包含所有传入字段的表。

    注意:writeFields 已被弃用,可能随时停止工作,但我没有找到任何替代品。

    编辑:writeFields 显然不再在模拟器中工作了......

    【讨论】: