当前位置: 首页 > 知识库问答 >
问题:

Firestore:文档的版本历史记录

充修能
2023-03-14

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

例如:我有一个名为offers的集合,其中包含多个文档,对应于多个offers。对于这些文档中的每一个,我都希望有更改的历史记录,比如谷歌文档上的更改。

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

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

通过这种方式,我可以查询整个报价集合,并获得报价数组和最新状态,因为它与集合本身处于同一级别。然后,如果我需要来自历史状态的特定内容,我可以查询特定报价的历史集合并获得其历史状态。这有意义吗?

我不确定反规格化,因为这似乎解决了我的问题,避免了复杂化。

同样,要求是:-能够获取具有最新状态(工作)的所有报价-能够加载特定历史状态(工作)

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

我错过了什么吗?

共有3个答案

盖和泰
2023-03-14

以下是我的团队利用谷歌云功能将每次收藏更新添加到Firestore中专门的“历史”收藏的解决方案(无需命令行):

>

  • 确定要监视的文档的路径:COLLECTION-NAME/{documentID}(或定义要监视的特定文档)

    创建一个新的Cloud Function(第一代,因为第二代还不支持FiRecovery触发器)

    将触发器设置为任何Firestore“写入”事件,监视步骤1中的文档路径。

    在Cloud Function的内联代码编辑器中,选择您选择的语言(我将使用Python),并在您的requriements.txt文件(或任何最新版本)中包含google-cloud d-fiRecovery==2.6.0

    最后,定义云函数的代码(确保正确导入Firestore!)

     def hello_firestore(event, context):
         resource_string = context.resource
         # print out the resource string that triggered the function
         print(f"Function triggered by change to: {resource_string}.")
    
         # now print out the entire event object
         print(str(event))
    
         # now import firestore and add event to the 'history' collection
         from google.cloud import firestore
         db = firestore.Client(project="YOUR-PROJECT-ID")
         newHistDoc = db.collection(u'history').add(event)
    

  • 陈茂
    2023-03-14

    我可以这样想。每个报价文档都将offerHistoryID作为编号。

    • 您可以为报价的版本化文档(例如offers_transactions)拥有单独的根集合。
    • 现在在提供文档上编写一个更新触发云函数,该函数将具有文档的后值和前值。
    • 在进行doc更新之前,您可以将之前的值与时间戳和最新的历史ID一起写入offers_transactions。
    • 将该offer的offer历史ID增加1,并使用新值更新文档。

    现在,您可以根据筛选器查询根集合offers_transactions以获取历史事务。通过这种方式,您可以保持根集合更干净。

    思想?

    楚嘉
    2023-03-14

    在我看来,您的上述架构可能会起作用,但您需要执行一些额外的数据库调用,因为Firestore查询很浅。这意味着 Firestore 查询只能从运行查询的收集中获取项目。Firestore 不支持跨不同集合的查询。因此,您无法在单个查询中获取一个文档以及该文档集合下托管的相应历史记录版本。

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

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

    如果要显示报价的所有历史版本,则需要单个查询。因此,您只需在<code>offerId</code>集合上附加一个侦听器,并一次性获取所有offer对象(文档)。

    但是,如果您只想获取报价的最后一个版本,那么您应该在每个报价对象下添加一个时间戳属性并根据它的降序查询数据库。最后只需进行限制(1)调用即可!

    编辑:

    根据您的评论:

    我需要一份所有报价及其最新数据的列表

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

    Firestore-root
       |
       --- offers (collection)
            |
            --- offerHistoryId (document)
            |        |
            |        --- date: //last edited timestamp
            |        |
            |        --- //Offer details
            |
            --- offerHistoryId (document)
                     |
                     --- date: //last edited timestamp
                     |
                     --- //Offer details
    

    这种做法称为非规范化,是Firebase的常见做法。如果您是NoQSL数据库的新手,我建议您观看此视频,为了更好地理解,Firebase数据库的非规范化是正常的。它适用于Firebase实时数据库,但同样的规则适用于云Firestore。

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

    在您的特殊情况下,当您想要创建一个要约时,您需要在两个地方添加它,一个在您的< code>offerId集合中,另一个在您的< code>offers集合中。一旦创建了报价的新历史版本,您只需再执行一项操作。如前所述,将< code>offerHistoryId文档添加到< code>offerId集合中,将相同的对象添加到< code>offers集合中,但是在这种情况下,您需要从< code>offers集合中删除该报价的旧版本。

     类似资料:
    • 本页内容包括: XCode6.4 Beta Swift语法文档更新 XCode6.3正式版 Swift语法文档更新 XCode6.2正式版 Swift语法文档更新 XCode6.2 Beta3 Swift语法文档更新 XCode6.2 Beta2 Swift语法文档更新 XCode6.2 Beta1 Swift语法文档更新 XCode6.1.1正式版 Swift语法文档更新 XCode6.1 Sw

    • 历史版本信息请查看SDK中心的版本信息。

    • 更多历史版本信息请查看SDK中心的版本信息。 V3.9.0.6( 更新时间:2018-06-10 ) 新增信息流分析功能,针对列表栏目的智能分析 优化SDK基础性能,提升稳定性 V3.9.0.0( 更新时间:2018-03-16 ) 新增自定义名单方式创建分群 支持上传用户识别ID,标记业务目标用户 错误报告升级,支持异常信息主动上报并展示 优化SDK开发者日志输出 V3.8.2.2( 更新时间:

    • V1.3.1 Mobile SDK : 点击下载 文档 :点击下载

    • 1.5.0 access log: added fields for UPSTREAM_LOCAL_ADDRESS and DOWNSTREAM_ADDRESS. admin: added JSON output for stats admin endpoint. admin: added basic Prometheus output for stats admin endpoint. Hist

    • 更新时间:2019-11-15 11:03:00 1.10.0(2019-11-15) 新功能 服务开发增加移动推送应用节点 1.9.0(2019-10-30) 新功能 支持非物模型设备的mqtt topic订阅与下发 支持监听设备上下线动作,进行规则触发 数据源的时间类型数据支持变量时间 交互优化:日志结构化 1.5.0(2019-07-20) 新功能 服务开发增加人工智能相关节点,包含人脸识别