如何在 onUpdate 函数中通过从同一集合中读取来更新同一文档

Posted

技术标签:

【中文标题】如何在 onUpdate 函数中通过从同一集合中读取来更新同一文档【英文标题】:How to update the same document with a read from the same collection in an onUpdate function 【发布时间】:2019-11-06 03:30:57 【问题描述】:

我正在尝试使用来自同一集合的读取值更新触发 onUpdate 云函数的同一个文档。 这是在 Flutter 中制作的一种聊天应用程序中,将先前对查询的响应复制到现在正在更新的文档中,以便在应用程序中显示。

代码确实有效,但是当用户快速响应两个单独的查询时,他们都读取了相同的最新响应,因此设置了相同的 previousResponse。这必须归结为颤振和/或云功能的异步性质,但我不知道在哪里等待,或者是否有更好的方法来制作该功能,所以它永远不会为同一个用户触发 onUpdate,直到前一个触发器完成。 最后一部分听起来也有点像个坏主意。

到目前为止,我尝试将读取/更新保留在事务中,但这似乎仅适用于单个函数调用,而不适用于它们是异步的。 还想我可以通过读取客户端事务中的先前响应来修复它,但是当不使用服务器 API 时,firebase 不允许从事务中的集合中读取。

async function setPreviousResponseToInquiry(
  senderUid: string, 
  recipientUid: string, 
  inquiryId: string) 

    return admin.firestore().collection('/inquiries')
    .where('recipientUid', '==', recipientUid)
    .where('senderUid', '==', senderUid)
    .where('responded', '==', true)
    .orderBy('modified', 'desc')
    .limit(2)
    .get().then(snapshot => 
      if (!snapshot.empty && 
          snapshot.docs.length >= 2) 
        return admin.firestore()
          .doc(`/inquiries/$inquiryId`)
          .get().then(snap => 
          return snap.ref.update( 
            previousResponse: snapshot.docs[1].data().response 
          )
        )
      
    )

【问题讨论】:

【参考方案1】:

我看到了三种可能的解决方案:

    在服务器上使用事务,确保您写入的更新必须基于您读取的数据的版本。如果您写入的值取决于触发 Cloud Function 的数据,您可能需要在事务中重新读取该数据。 不要使用 Cloud Functions,而是从客户端运行所有更新。这允许您使用事务来防止竞争条件。 如果无法使用事务,您可能必须在上游数据(触发写入的数据)和正在更新的扇出数据中都包含自定义版本号。然后,您可以使用安全规则来确保只有当下游数据的版本与当前上游数据匹配时才能写入下游数据。

我会按照上述顺序考虑/尝试它们,因为它们会逐渐参与进来。

【讨论】:

1.我已经尝试过围绕搜索和结果更新进行交易,但这似乎没有什么不同,因为集合搜索显然没有锁定更新。我在 Google 的文档中看不到任何关于此的内容。 2.不幸的是,这是不可能的,因为客户端事务不允许进行集合搜索,而只能用于特定文档。至于3,我不确定如何做到这一点。你有一个例子或者你能详细说明这个方法吗?

以上是关于如何在 onUpdate 函数中通过从同一集合中读取来更新同一文档的主要内容,如果未能解决你的问题,请参考以下文章

在 Access 中通过 VBA 存储集合

如何在bash脚本中通过函数调用将参数/参数从一个函数传递到另一个函数[重复]

在 MySQL Workbench 中通过快捷方式执行语句

通过从每个集合中仅选择一个值来选择 k 个大小的子集

如何在 Swift 中通过 MR 的 id 从 coredata 中选择一条记录

Firebase Cloud 函数触发两次 onUpdate