在 Firestore 中构建此类数据的正确方法是什么?
您需要知道构建 Cloud Firestore 数据库没有没有“完美”、“最佳”或“正确”的解决方案。最好和正确的解决方案是适合您的需求并使您的工作更轻松的解决方案。还要记住,在 NoSQL 数据库的世界中也没有单一的“正确的数据结构”。所有数据都经过建模以允许您的应用程序需要的用例。这意味着适用于一个应用程序的内容可能不足以用于另一个应用程序。所以没有适合每个人的正确解决方案。 NoSQL 类型数据库的有效结构完全取决于您打算如何查询它。
您构建数据的方式在我看来不错。一般来说,有两种方法可以实现相同的目标。第一个是在产品对象中保留提供者的引用(就像您已经做的那样)或复制产品文档中的整个提供者对象。最后一种技术称为denormalization,在 Firebase 中是一种非常常见的做法。因此,我们经常在 NoSQL 数据库中复制数据,以适应其他情况下可能无法进行的查询。为了更好地理解,我建议您观看此视频,Denormalization is normal with the Firebase Database。它适用于 Firebase 实时数据库,但同样的原则也适用于 Cloud Firestore。
另外,当您复制数据时,需要记住一件事。同样,您正在添加数据,您需要维护它。换句话说,如果你想更新/删除一个提供者对象,你需要在它存在的每个地方都这样做。
您现在可能想知道,哪种技术最好。一般来说,在 NoSQL 数据库中存储引用或复制数据的最佳方式完全取决于项目的要求。
所以你应该问自己一些关于你想要复制的数据的问题,或者只是把它作为参考:
- 是静态的还是会随着时间而改变?
- 如果是这样,您是否需要更新每个重复的数据实例以使它们保持同步?这也是我之前提到的。
- 谈到 Firestore,您是针对 performance 还是 cost 进行优化?
如果您的重复数据需要同时更改并保持同步,那么您将来可能很难让所有这些重复数据保持最新状态。这也可能意味着您花费大量资金来保持所有这些文档的最新状态,因为每次更改都需要对每个文档进行读取和写入。在这种情况下,仅持有引用将是获胜的变体。
在这种方法中,您编写的重复数据非常少(几乎只是Provider ID)。因此,这意味着您编写此数据的代码将非常简单且非常快速。但是在读取数据时,您需要从两个集合中加载数据,这意味着额外的数据库调用。对于合理数量的文档,这通常不是一个大的性能问题,但肯定需要更多的代码和更多的 API 调用。
如果您需要非常快速的查询,您可能希望复制更多数据,以便客户端只需读取每个查询项目的一个文档,而不是多个文档。但是您也可以依赖本地客户端缓存,这会降低成本,具体取决于客户端必须读取的数据。
在这种方法中,您为每个 product 文档复制 provider 的所有数据。这意味着编写此数据的代码更复杂,而且您肯定要存储更多数据,为每个产品文档多提供一个提供程序对象。而且您需要弄清楚是否以及如何保持每个文档的最新状态。但另一方面,阅读product 文档现在可以在一个 阅读中为您提供有关provider 文档的所有信息。
这是 NoSQL 数据库中的一个常见考虑因素:您通常需要考虑写入性能和磁盘存储与读取性能和可扩展性。
对于是否复制某些数据的选择,很大程度上取决于您的数据及其特征。您必须根据具体情况考虑。
所以最后,请记住,两者都是有效的方法,而且它们都没有比另一个更好。这完全取决于您的用例是什么,以及您对这种复制数据的新技术的适应程度。数据复制是加快读取速度的关键,不仅在 Cloud Firestore 或 Firebase 实时数据库中,而且在一般情况下。每当您将相同的数据添加到不同的位置时,您都在复制数据以提高读取性能。不幸的是,作为回报,您有更复杂的更新和更高的存储/内存使用率。但是您需要注意,Firebase 实时数据库中的额外调用并不昂贵,在 Firestore 中是。多少重复数据与额外的数据库调用对您来说是最佳的,这取决于您的需求以及您是否愿意放弃“单点定义心态”,这可以说是非常主观的。
完成几个 Firebase 项目后,我发现如果我复制数据,我的阅读代码会变得非常简单。但当然,编写代码同时变得更加复杂。这是这两者和您的需求之间的权衡,决定了您的应用程序的最佳解决方案。此外,更准确地说,您还可以使用现有工具衡量应用程序中发生的情况并做出相应决定。我知道这不是一个具体的建议,而是软件开发。一切都是为了衡量事物。
还请记住,某些数据库结构更容易使用某些安全规则进行保护。所以尝试找到一个可以使用Cloud Firestore Security Rules 轻松保护的架构。
还请查看我在此 post 中的回答,我在此详细解释了 Firestore 中的 collections、maps 和 arrays。