Firestore:文档的版本历史记录

Seb*_*čić 6 data-modeling firebase google-cloud-firestore

我正在寻找一种构造Firestore数据库的适当方法,以处理单个集合中文档的多个版本历史记录。

例如:我有一个集合命名提供其有多个文件对应于多重优惠。对于这些文档中的每一个,我都希望有更改历史记录,例如Google文档中的更改。

由于文档仅支持直接添加字段或嵌套另一个集合,因此我想到了以下结构:

collections: offers
 - documents: offer1, (offer2, offer3, ...)
     - fields populated with latest version of the offer content
     - nested collection named history
         - nested documents for each version (v1, v2, v3), which in turn have fields specifing state of each field in that version. 
Run Code Online (Sandbox Code Playgroud)

由于我拥有最新状态,而不是嵌套收集历史记录,因此这似乎有点复杂。在平面结构中,数组中的最新项是最新状态,还是类似的状态,这可能是某种原因吗?

另外,单击按钮即可生成历史记录状态,因此我不需要将所有可能的更改保存在历史记录中,而只需在用户保存时添加快照即可。

我想将Firebase用作我的数据库,因为我还需要其他一些东西,因此我暂时不考虑其他解决方案。

谢谢!

编辑:根据亚历克斯的回答,这是我对此的另一种看法。

Firestore-root
   |
   --- offers (collection)
        |
        --- offerID (document)
        |   (with fields populated )
        |        |
        |        --- history (collection) //last edited timestamp
        |            |
        |            --- historyId
        |            --- historyId
        |
         --- offerID (document)
            (with fields populated with latest changes)
                 |
                 --- history (collection) //last edited timestamp
                     |
                     --- historyId
                     --- historyId
Run Code Online (Sandbox Code Playgroud)

这样,我就可以查询整个offers馆藏并获取要约阵列以及最新状态,因为它与馆藏本身处于同一级别。然后,如果我需要历史记录状态中的特定内容,则可以查询特定商品的历史记录收集并获取其历史记录状态。这有意义吗?

我不确定非规范化,因为这似乎解决了我的问题并避免了复杂性。

再次,要求是:-能够获取具有最新状态的所有报价(有效)-能够加载特定的历史记录状态(有效)

每当我用新状态更新历史记录集合时,我都会使用相同的最新状态直接覆盖offerID集合中的字段。

我想念什么吗?

Ale*_*amo 5

在我看来,您的上述架构可能有效,但由于Firestore查询比较浅,您需要进行一些额外的数据库调用。这意味着Firestore查询只能从运行查询的集合中获取项目。Firestore不支持跨不同集合的查询。因此,您无法通过单个查询获取一个文档以及该文档的集合下托管的相应历史版本。

我能想到的一种可能的数据库结构是使用这样的单个集合:

Firestore-root
   |
   --- offerId (collection)
        |
        --- offerHistoryId (document)
        |        |
        |        --- //Offer details
        |
        --- offerHistoryId (document)
                 |
                 --- //Offer details
Run Code Online (Sandbox Code Playgroud)

如果要显示商品的所有历史版本,则需要一个查询。因此,您只需要在offerId集合上附加一个侦听器,即可一次性获得所有商品对象(文档)。

但是,如果只想获取商品的最新版本,则应在每个商品对象下添加一个timestamp属性,并根据其降序查询数据库。最后,只需limit(1)拨打电话即可!

编辑:

根据您的评论:

我需要获取所有最新报价的清单

在这种情况下,您需要创建一个名为的新集合offers,该集合将保存商品的所有最新版本。您的新收藏应如下所示:

Firestore-root
   |
   --- offers (collection)
        |
        --- offerHistoryId (document)
        |        |
        |        --- date: //last edited timestamp
        |        |
        |        --- //Offer details
        |
        --- offerHistoryId (document)
                 |
                 --- date: //last edited timestamp
                 |
                 --- //Offer details
Run Code Online (Sandbox Code Playgroud)

denormalization在Firebase中,这种做法被称为并且是一种常见的做法。如果您是NoQSL数据库的新手,建议您观看此视频,对于更好的了解,Firebase数据库的非规范化是正常的。它适用于Firebase实时数据库,但相同的规则适用于Cloud Firestore。

另外,在复制数据时,请记住一件事。用与添加数据相同的方式,您需要对其进行维护。换句话说,如果您想更新/删除项目,则需要在它存在的每个位置进行。

在特定情况下,当您要创建商品时,需要在两个地方添加商品,一次在您的offerId收藏中,一次在您的offers收藏中。创建要约的新历史记录版本后,只需执行一项其他操作。与以前一样,在offerHistoryId文档offerId集中添加文档,在文档集中添加相同的对象offers,但是在这种情况下,您需要从文档集中删除商品的旧版本offers

  • 这篇文章已经很老了,但对于那些不知道从 2020 年起 firestore 支持所谓的“collectionGroup 查询”的人来说,这意味着您可以在项目的 firestore 数据库中查询具有相同名称的多个集合,您可以阅读有关它的更多信息[此处](https://firebase.google.com/docs/firestore/query-data/queries)我希望这可以回答您在评论中的问题!@SebastijanDumančić (3认同)
  • 谢谢亚历克斯!我实际上不知道你不能得到深度嵌套的对象。刚试过,你是对的。然而,这种结构也不能解决所有问题。例如,我需要获取所有报价及其最新数据的列表,在这里我看不到这样做的方法,因为每个报价都在它自己的集合中。我很好奇你是否有办法解决这个问题。之后我可以分享我的想法:) (2认同)
  • 噢,我明白。我将立即更新我的答案。 (2认同)
  • 它几乎与第一个相同。恕我直言,如果我是你,我将使用非规范化。听起来有些怪异,但这很容易。欢迎您,塞巴斯蒂安,加油! (2认同)
  • 我会再看一些。谢谢您的帮助 :) (2认同)