Firestore:文档的版本历史记录

时间:2018-11-23 07:38:55

标签: firebase google-cloud-firestore data-modeling

我正在寻找一种构建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. 

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

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

我想将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

通过这种方式,我可以查询整个offers集合,并获得要约的数组以及最新状态,因为它与集合本身处于同一级别。然后,如果我需要历史记录状态中的特定内容,则可以查询特定商品的历史记录收集并获取其历史记录状态。这有意义吗?

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

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

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

我想念什么吗?

2 个答案:

答案 0 :(得分:2)

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

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

Firestore-root
   |
   --- offerId (collection)
        |
        --- offerHistoryId (document)
        |        |
        |        --- //Offer details
        |
        --- offerHistoryId (document)
                 |
                 --- //Offer details

如果要显示要约的所有历史记录版本,则需要一个查询。因此,您只需要在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

这种做法称为denormalization,是Firebase的常见做法。如果您不熟悉NoQSL数据库,建议您观看此视频Denormalization is normal with the Firebase Database,以更好地理解。它用于Firebase实时数据库,但相同的规则适用于Cloud Firestore。

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

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

答案 1 :(得分:0)

我可以这样想。每个 offers 文档将具有 offerHistoryID 作为编号。

  • 您可以为商品的版本控制文件提供一个单独的根集合(例如 offers_transactions )。
  • 现在在要价文档上编写一个更新触发云功能,该功能将在文档的值之后和之前。
  • 在进行文档更新之前,您可以将之前值以及时间戳和最新的historyID写入 offers_transactions
  • 将该商品的offerHistoryID增加1,并使用新值更新文档。

现在,您可以根据过滤条件查询根集合 offers_transactions 的历史交易。这样,您可以使根集合提供的内容更干净。

有想法吗?