如何在保持访问权限不变的同时将 Firestore 文档从一个子集合共享到另一个子集合?

Posted

技术标签:

【中文标题】如何在保持访问权限不变的同时将 Firestore 文档从一个子集合共享到另一个子集合?【英文标题】:How to share Firestore documents from one sub-collection to another while keeping the access rights intact? 【发布时间】:2021-06-09 05:38:15 【问题描述】:

这就是我的 Firestore 数据库的结构

例如,现在我想让userAuserB 共享Recipe2

当我获取他/她的食谱时,我也想在UserB UI 中列出Recipe2。 我在我的 Swift 代码中获取食谱的方式是用户只能查看他/她的文档或集合,即userB 永远不能查询/阅读userA's 食谱。 考虑到我以后可能会允许用户B修改共享食谱,我该如何实现共享功能?我不想创建多个副本,我的 Firestore 规则设置为不允许任何用户读取其他用户的数据,这一切是最好的解决方案吗?

【问题讨论】:

您为什么不愿意复制记录?非规范化是 NoSQL 标准操作过程。对于可扩展的解决方案,您必须授予用户对用户数据的访问权限(可以并且应该受到限制)或对配方进行非规范化。 如何授予用户 B 访问权限以读取用户 A 的食谱?我想知道我必须在什么级别上管理这些权利?在 FB 规则中还是在我的代码中? 如果您可以对数据进行非规范化并允许在数据库中存在配方副本,这就是 NoSQL 的工作原理,我可以推荐一种架构。否则,请参阅此链接了解详细的安全规则:fireship.io/snippets/firestore-rules-recipes 【参考方案1】:

有很多方法可以解决这个问题,如果不了解整个用例,就不可能提供最佳解决方案。

让我建议一下:

当您遇到包含我的数据、您的数据和我们的数据的情况时,通常最好将我们的数据放在一个单独的集合中,使用 uid 和规则来确定谁可以访问哪些数据。例如

users
   UserA
      ...
   UserB
      ...
recipes
   recipe0
      owner: UserA
      name: "pasta fazul"
      ingredients
         ...
      visible_to
         UserB

然后是一条规则,允许用户读取他们的 uid 列在 visible_to 中的食谱,并且只有匹配所有者 uid 的所有者才能进行更改。

【讨论】:

visible_to 是子集合还是数组? @liquid 有很多选择;您可以使用和数组或地图或许多其他选项。数组会很好,因为您可以利用 .arrayContains 进行查询等 - 如果您想知道某个用户可以访问哪些食谱。 数组的问题在于,由于文档大小的限制,它不能很好地适应不断增长的用户群。而子集合的问题是查询困难。 @liquid 我不会为这个用例建议一个子集合——尽管它可以工作。请记住,可伸缩性是相对的,总体情况是您有一个文档,其中存储了一个索引和 uid 数组,这是少量信息。 Firebase 几乎没有什么是不可扩展的,如果有的话,所以在每个配方中处理 数千个 用户是没有问题的。 一个数组可以处理成千上万的用户,但不能更多。它无法处理一百万用户。它应该能够。仅有的两个可扩展解决方案是修改访问权限或非规范化配方。【参考方案2】:

就像我在 cmets 中所说的那样,您必须授予用户访问彼此文档的权限,或者对文档本身进行非规范化。在 NoSQL 中对数据进行非规范化不仅是标准的操作过程,而且是一种高效的优化工具,需要时才能使用。

首先,Firestore 文档不能超过 1 MB,这意味着对于相对较小的用户群,您可以选择不同的架构(这样可以为您节省读写费用)。但是,我建议不要构建不随用户群扩展的数据,因为用户群规模可能是最难预测的指标。该解决方案可以与几乎任何规模的用户群一起扩展。其次,该解决方案的设计使得当配方的所有者修改该配方时,可以轻松找到并更新他们的共享实例(如果需要)。第三,该解决方案的设计使得当显示共享食谱的用户修改该食谱时,可以轻松找到原始作者并且可以更新或注释该食谱(如果需要)。最后,该解决方案仅通过两个不需要访问其他用户数据的简单查询就可以显示用户的食谱(用户拥有和借用)。

[collection]
    <document>

[users]
    <userA>
        [my-recipes]
            <recipe1>
            <recipe2>
            <recipe3>
                [sharing-with]
                    <userB> (acts as a bookmark with the user's info)

    <userB>
        [my-recipes]
            <recipe4>
            <recipe5>
            <recipe6>
        [shared-recipes]
            <recipe3> (contains an owner field)

【讨论】:

我将向我的团队展示这个令人难以置信的解决方案,这里的问题是我们需要两个查询来更新食谱和两个查询来阅读食谱。感谢您提供出色的解决方案!

以上是关于如何在保持访问权限不变的同时将 Firestore 文档从一个子集合共享到另一个子集合?的主要内容,如果未能解决你的问题,请参考以下文章

Firebase 客户端对您的 Cloud Firestore 数据库的访问权限将在 3 天后到期 [重复]

如何将所有行的 MS Word 2010 表行高属性从“完全”更改为“至少”,同时保持指定的行高值不变

客户对 Cloud Firestore 数据库的访问权限将在 1 天后到期 [重复]

将外部域指向子域,同时保持域不变

使用访问规则中的字段写入 Firestore 时缺少权限或权限不足

是否可以将与不同行名关联的值添加在一起,同时保持其他行不变?