情况:
我正在创建一个基本上如下所示的数据结构:
events:
adminUserId: 1337
users:
questiongroups:
questions:
text: 'foo',
value: 42
因此,事件是一个列表,每个事件的用户,每个事件的每个用户的问题组以及每个事件的每个用户的每个问题组的问题。其中一些还有ID等附加字段,但为了简单起见,我省略了它们。
这个数据结构很好,因为我可以限制访问,只允许用户操纵他们自己的问题组列表和问题子列表 - 使用firestore规则。
问题:
每个事件都有一个管理员用户,该用户应该能够CRUD他所管理的所有数据(通过adminUserId)。或者更准确地说,他应该能够在他的UI中的一个大表中看到所有数据以用于一个事件。它是一个小规模的应用程序,大约有20个用户,可能有50个问题组,平均有5个问题。基本上就是这样:
| QuestionGroup1_Question1 | QuestionGroup1_Question2 | QuestionGroup2_Question1
user #1 | foo | bar | 1337
user #2 | foo | bar | 1701
现在我希望能够以最少的查询(可能只有一个)查询一个事件的数据。 但是到目前为止我收集的内容是你只能在Firestore上执行浅层查询,因此我只能检索“事件”的字段。但是然后必须查询每个用户,然后查询每个问题组,然后再次查询每个问题 - 即使这么小的数字也相当于大量的查询。
基本上我的问题是:我有什么选择? 我已经读过,可以在文档中嵌套复杂的对象。但根据https://firebase.google.com/docs/firestore/manage-data/structure-data,您无法对其进行查询,那么我是否仍可以通过Firestore规则限制访问权限?我发现在使用Firebase实时数据库时你可以用通配符做到这一点,但是Firestore呢?
我很乐意了解一些选择。 谢谢!
答案 0 :(得分:0)
您可以查询嵌套数据,但不能查询嵌套列表。您仍然可以在使用对象时模仿列表(即{ 0: 'first', 1: 'second' }
),但我不建议这样做。
以下是查询嵌套数据的示例:
db.collection('questions').where('topic.coding', '==', true)
您无法对Firestore文档中的嵌套数据强制执行读取规则。这需要能够使用select
(目前仅在firebase-admin中可用)并且能够在类似于request.query
(request)的规则中查看请求信息。
编辑:此外,是(写入)
您可以对写入的所有数据(包括嵌套对象和列表)强制执行写入规则。由于您可以看到写入(request.resource)的整个有效负载,因此您可以根据文档或数据库中的其他数据制定规则,以确定哪些路径是可覆盖的和/或允许的值。
展平您的数据库结构。类似的东西:
match /events/{event_id} {
match /users/{user_id} {
}
match /groups/{group_id} {
}
match /questions/{question_id} {
// check if request.auth.uid is creator
}
}
我不确定每个文档中的内容,因此我无法确定实现Firestore结构的最佳方式,以便优化查询和简化规则。
由于Firestore规则不像Firebase的RTDB规则那样级联,因此展平结构并不会使规则复杂化。唯一的缺点(我认为是好处)需要在扁平化集合上进行非浅层查询的索引(即用户希望查看关于“编码”主题的所有问题)。
我的最终建议是找出所有可能的查询约束(即user_id,topic,group_id),确定哪些是必需的(可能是user_id和/或group_id)和基于强制约束的嵌套集合(即/ users / {user_id} / questions / {q_id},如果查询问题必须使用“user_id”)。对于规则,您始终只需将子集合添加到需要安全性的文档(或角色/权限信息),其中子集合中的文档ID与请求用户的ID 匹配(即安全文档)必须存在,并具有访问父文档的适当角色/权限)。
在设计数据库结构时,这并没有解决所有问题,但通过帮助识别“自然分层”(Choose a Data Structure)数据,这是一个很好的起点。