当前位置: 首页 > 知识库问答 >
问题:

关于子集合的云Firestore规则

艾自强
2023-03-14

我正在开发一款iOS应用程序,它有(哇,惊喜!)聊天功能。整个应用程序大量使用Firebase工具,对于数据库,我正在使用新的云Firestore解决方案。

目前我正在使用数据库规则加强安全性,但我对自己的数据模型有点挣扎:)这可能意味着我的数据模型选择不当,但我真的很满意,除了实现规则部分。

模型的对话部分如下所示。在我的数据库的根目录下,我有一个对话集合:

/conversations/$conversationId
        - owner // id of the user that created the conversation
        - ts // timestamp when the conversation was created
        - members: {
                $user_id_1: true // usually the same as 'owner'
                $user_id_2: true // the other person in this conversation
                ...
          }
        - memberInfo: {
                // some extra info about user typing, names, last message etc.
                ...
          }

然后我对每个对话都有一个子集合,称为消息。消息文档是一个非常简单且仅包含有关每个发送消息的信息的文档。

/conversations/$conversationId/messages/$messageId
        - body
        - sender
        - ts

对话文档中的规则非常简单,易于实现:

match /conversations/{conversationId} {
  allow read, write: if resource.data.members[(request.auth.uid)] == true;

  match /messages/{messageId} {
        allow read, write: if get(/databases/$(database)/documents/conversations/$(conversationId)).data.members[(request.auth.uid)] == true;
  }
}

我的问题是对话中的messages子集合。上面的方法很有效,但我不喜欢在那里使用get()调用。每个get()调用都会执行读取操作,因此会影响月末的账单,请参阅文档。

如果我正在构建的应用程序成功,这可能会成为一个问题,文档读取当然非常少,但是每次用户打开对话时都这样做似乎有点低效。我真的很喜欢我模型中的子集合解决方案,但不确定如何有效地实现这里的规则。

我对任何数据模型更改持开放态度,我的目标是评估没有这些get()调用的规则。任何想法都非常受欢迎。

共有2个答案

长孙燕七
2023-03-14

如果想保存这些额外的读取,实际上可以基于自定义声明实现“缓存”。

例如,您可以在对象"对话"下的自定义声明中保存用户有权访问的聊天。请记住,自定义声明的限制为1000字节,如其留档中所述。

限制的一个解决方法是仅在自定义声明中保存最近的对话,例如前50个。然后在安全规则中,您可以这样做:

allow read, write: if request.auth.token.conversations[conversationId] || get(/databases/$(database)/documents/conversations/$(conversationId)).data.members[(request.auth.uid)] == true;

如果你已经在使用云功能来缓和发布后的消息,那么这一点尤其重要,你只需要更新自定义声明即可

蒋联
2023-03-14

老实说,我觉得你对自己的结构没什么意见,而且get按原样打电话。原因如下:

>

一般来说,我不喜欢在安全规则中优化定价。是的,每个操作可能会有一到两次额外的读取,但这可能不会以同样的方式给您带来麻烦,比如,编写糟糕的云函数可能会带来麻烦。这些都是你最好优化的领域。

 类似资料:
  • 我正在从Firebase实时数据库切换到云Firestore。我的数据库包含拥有存储的用户,每个存储都包含盒子。每个用户都可以拥有多个包含盒子的存储器。每个存储可以包含几个盒子。每个箱子只能放在一个仓库里。 在我应用程序的主视图中,对于该特定用户,我需要列出所有存储以及每个存储中的框,如下所示: 然后,用户应该能够点击每个框以查看内容和更多信息。 在Firebase实时数据库中,每个用户只需一个请

  • 我目前正在使用firestore的子集合模式,它允许我将集合保存在文档中。 这意味着对于我的组织集合,我有组织文档,每个文档都有子集合,比如:项目、成员等等。。。通过这种方式,我可以始终保证,对于一个特定的文档,我以一种可扩展的方式将其所有特定的数据都限定在它的范围内。这解决了在文档属性中嵌入数据(比如数组)的问题,这些数据可能会失控。 现在,我在mongoDB中没有找到这样的东西。我确实发现Do

  • 假设我们有一个名为'Todos'的根集合。 此集合中的每个文档都有: null null

  • 我正在尝试为firestore中的社交媒体应用程序组织数据。为帖子创建一个新集合或将其放入用户的子集合更好吗? 深度应该是一样的,但是一种方式比另一种方式有什么优势吗? 创建新集合: 职位(集合) 用户(集合) 用户中的子集合: 用户(集合)

  • 假设我有一个集合,其中包含子集合。餐厅权限设置在餐厅文档中,如下所示: 餐馆 任何有权访问餐厅的人也可以访问它的任何子集合,包括子集合。这是安全规则: 安全规则 查询餐厅列表可以这样完成,而且效果很好: 查询餐厅 现在如何查询子集合?我知道Firestore需要根据查询推断权限,而不查看底层数据。从逻辑上讲,这应该是可能的,因为任何可以访问的人也可以访问子集合。但是我如何组合这个子集合查询,以便F

  • 我有一个困扰我好几天的问题。我正在尝试创建一个从Firestore数据库读取的Firebase云函数。 我的Firestore DB如下所示: 问题是我无法像这样列出: 如果我尝试这样做,我会得到空响应,就像我的集合中没有用户一样。 但我尝试直接访问用户它可以工作: 我的完整代码: 有人知道我做错了什么吗?非常感谢。