如何使用onUpdate函数中的同一集合中的读取内容更新同一文档

时间:2019-06-24 10:28:54

标签: asynchronous flutter google-cloud-firestore google-cloud-functions

我正在尝试使用同一集合中的读取值来更新触发onUpdate云功能的同一文档。 这是使用Flutter开发的一种聊天应用程序,其中先前对查询的回复被复制到现在正在更新的文档中,以便在应用程序中更轻松地显示。

该代码确实有效,但是当用户快速响应两个单独的查询时,他们都读取相同的最新响应,因此设置了相同的previousResponse。这一定要归因于flutter和/或云函数的异步特性,但是我无法弄清楚在哪里等待,或者是否有更好的方法来创建该函数,因此它永远不会为同一用户触发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 个答案:

答案 0 :(得分:0)

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

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

随着它们逐渐参与其中,我会按上述顺序考虑/尝试它们。