【问题标题】:Firestore subcollection vs arrayFirestore 子集合与数组
【发布时间】:2019-04-30 18:39:20
【问题描述】:

首先,我了解 Firestore 的工作原理,并花费了大量时间评估不同的方法以获得良好的结构。我仍在考虑以下情况:

有一个已知食谱的数据库。用户可以添加菜谱,但必须确认它们是真实的菜谱,而不仅仅是一些变体。因此,每个用户都可以从用户生成的食谱列表中选择收据来说明他们知道如何烹饪(或添加新的)。

现在我希望用户与其他人分享他们的收据列表,但我不确定如何使用 Firestore 最好地实现这一点。诀窍是,我想一次显示所有食谱,并且不想对它们进行分页。

我目前正在评估两种可能性:

子集合

每当用户分享他的列表时,查看该列表的用户将不得不加载整个食谱列表,这可能会导致大量文档读取(我想实际上约为 50,在极少数情况下可能为 1000) .

优点:

  • 更自然的结构
  • 更易于维护(例如删除配方、检查特定配方是否存在)
  • 更容易添加字段(例如 timeOfCreation、comment、personalRating...)

缺点:

  • 从长远来看可能导致大量读取

数组

我可以将每个已知的食谱(id 和 imageURL)保存在数组中的用户文档中(或作为单个子文档“KnownRecipes”)。这个数组可以是

recipesKnown: [{rid: 293ndwa, imageURL: image1.com, timeAdded: 8371201332}, 
               {rid: 9012831, imageURL: image1.com, timeAdded: 8371201871},
               {rid: jd812da, imageURL: image1.com, timeAdded: 8371201118},
               ...
              ]

优点:

  • 每当有人想查看另一个用户的列表时,我只需要阅读一个文档
  • 读取用户列表可能更快

缺点:

  • 很难更新特定配方(例如,有人想要更改 imageURL:我需要在本地更改列表并将整个文档作为更新发送到服务器 - 因为我不能只更改数组中的单个元素)
  • 当用户决定拥有大约 1000 个食谱时(这可能永远不会发生,但它可以),可能会达到 Firestore 限制的 1MiB 限制。一种可能的解决方法是创建一个单独的文档并将这两个数组拆分为这两个文档。

对我来说,子集合的想法似乎是解决这个问题的更“干净”的解决方案,但也许我错过了一些关于为什么其中一个解决方案优于另一个的论点。

我最常见的查询如下(按重要性降序排列):

  • 用户可以烹饪哪些食谱
  • 将用户可以烹饪的食谱添加到用户列表中
  • 谁可以烹饪特定食谱(有一个 Recipe -> Cooks 子集合)
  • 更新用户可以烹饪的现有食谱

【问题讨论】:

  • 听起来你对两者之间的区别很了解。
  • 如果您询问 Firestore 子集合和数组之间的差异,我也可以说答案留在您的问题中。您还有其他与此相关的问题吗?
  • 好吧,如前所述,我希望遗漏一些可以帮助我更轻松地做出决定的重要优点/缺点。也不确定在这里(通过使用数组)进行糟糕的设计有多好,以将读取次数减少 100 倍。我很清楚其中的区别(除了我不知道使用数组的确切功能) .考虑到它在专用子文档中是顶级的,以下是否是一个合法的结构:[dynamicId]: {imageURL: "example.com", name: "SomeName"}, [dynamicID]: {...},...?所以我会用地图替换我的数组方法的概念。
  • @thomas 您最终是从其他来源获得答案,还是自己评估?我只是想听听,因为我想知道类似的问题。干杯
  • @riper 不,抱歉。我决定在我的案例中使用一个数组,但我对此并不是 100% 满意。

标签: firebase google-cloud-firestore


【解决方案1】:

您的问题的答案取决于您想要达到的可扩展性水平。

如果您想要存储的子数据量有限且非常低,则应使用数组,因为您减少了文档读取次数,这意味着成本更低。

如果您的子数据应该随着时间“无限”增加,您应该使用子集合。

如果您正在构建一个不应该向任何方向扩展的数据库(概念证明、非常小型的企业等),请选择您觉得更舒服的方式。

【讨论】:

    【解决方案2】:

    我正在研究同样的问题...

    其中一个问题是文档中保存的数据是否会超过 1MB,这是文档的限制。研究一下它可以在 1MB 中以纯文本形式保存多少,这真是太多了。尽管如此,如果它变得难以置信地大,它最终还是会崩溃。因此,如果您以大的方式思考子系列。

    如果我们必须使用 Firebase 元素逻辑,答案将是子集合。

    我仍然认为主要的一点是提取的数据。如果您致电用户,您将直接提取该 MB 数据。相反,它不会加载子集合,即使您加载了它,您仍然可以延迟加载。

    我猜你正在做子集合的那种设置。

    【讨论】:

    • 感谢您的意见。实际上我选择了数组,因为我总是希望在加载配置文件时同时加载所有食谱。
    • 太棒了!最后我两个都用。我需要这样,大声笑。感谢您的回复,我想知道您的选择。
    【解决方案3】:

    key 是一个额外的collection 的 con/pro

    key 有助于避免重复;但这需要考虑重复的定义是什么(可能会改变);

    array 的无键行为可以通过 auto-id 来模拟。

    附言@Thomas 在问题中的优缺点列表非常有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-03
      • 2020-08-10
      • 2020-08-19
      • 1970-01-01
      • 1970-01-01
      • 2019-02-19
      • 2021-11-25
      • 2019-07-25
      相关资源
      最近更新 更多