【问题标题】:Firestore: Reading multiple documents in transactionFirestore:在事务中读取多个文档
【发布时间】:2018-03-16 21:57:35
【问题描述】:

当我运行 Firestore 事务时,它给了我错误:

“事务中读取的每个文档也必须写入该事务中。”

但是我试图在事务中读取的所有文档也都被写入下面的代码中?

    db.runTransaction({ (transaction, errorPointer) -> Any? in
    let doc1: DocumentSnapshot
    let doc2: DocumentSnapshot
    let doc3: DocumentSnapshot

    do {
        try doc1 = transaction.getDocument(self.doc1Ref)
        try doc2 = transaction.getDocument(self.doc2Ref)
        try doc3 = transaction.getDocument(self.doc3Ref)
    } catch let fetchError as NSError {
        errorPointer?.pointee = fetchError
        return nil
    }



    // WRITES TO DOC1, DOC2, DOC3
    guard let userPostCount = doc1.data()?["postCount"] as? Int,
        let locationPostCount = doc2.data()?["postCount"] as? Int,
        let itemPostCount = doc3.data()?["postCount"] as? Int,
        let locationAvgRating = doc2.data()?["averageRating"] as? Float,
        let itemAvgRating = doc3.data()?["averageRating"] as? Float else { return nil }


    // Create post on another document not in transaction
    transaction.setData(post.dictionary, forDocument: self.doc4Ref)


    // Update counts for #userPosts, #locationPosts, #itemPosts, avgLocationRating, avgItemRating
    transaction.updateData(["postCount": userPostCount + 1], forDocument: self.doc1Ref)

    let newAvgLocationRating = ((avgLocationRating * Float(locationPostCount)) + Float(post.rating)) / (Float(locationPostCount) + 1.0)
    transaction.updateData(["postCount": locationPostCount + 1, "averageRating": newAvgLocationRating], forDocument: self.doc2Ref)

    let newAvgItemRating = ((avgItemRating * Float(itemPostCount)) + Float(post.rating)) / (Float(itemPostCount) + 1.0)
    transaction.updateData(["postCount": locationPostCount + 1, "averageRating": newAvgItemRating], forDocument: self.doc3Ref)


    // Add postID to user and location
    transaction.setData(["postID": self.postRef.documentID, "locationID": post.locationID, "itemID": post.itemID, "rating": post.rating, "timestamp": post.timestamp], forDocument: self.doc1Ref.collection("posts").document(self.postRef.documentID))

    transaction.setData(["postID": self.postRef.documentID, "rating": post.rating, "timestamp": post.timestamp], forDocument: self.doc3Ref.collection("posts").document(self.postRef.documentID))


    return nil
}) { (object, error) in
    if let error = error {
        print(error)
    } else {
        print("done")
    }
}

难道不能在一个事务中做多个 .getDocument(documentReference) 吗?

还有其他方法可以解决这个问题吗?

【问题讨论】:

  • 有什么理由不显示这些内容?很难看出你是否做错了什么。我们也看不到你是如何分配三个 refs 的。
  • 刚刚添加了@DougStevenson的写入

标签: swift firebase google-cloud-firestore


【解决方案1】:

您应该将所有if 操作放在do 和else 操作在catch 中

不要在街区外使用它们。

这就是错误的意思"Every document read in a transaction must also be written in that transaction."。
例如。你的代码

// WRITES TO DOC1, DOC2, DOC3
guard let userPostCount = doc1.data()?["postCount"] as? Int,
    let locationPostCount = doc2.data()?["postCount"] as? Int,
    let itemPostCount = doc3.data()?["postCount"] as? Int,
    let locationAvgRating = doc2.data()?["averageRating"] as? Float,
    let itemAvgRating = doc3.data()?["averageRating"] as? Float else { return nil }

正在使用 doc1,doc2 在 do catch 块范围之外进行操作

【讨论】:

    【解决方案2】:

    我刚刚注意到您正在使用 Apple 的 swift 脚本。我的回答是基于标准的 JavaScript,但我希望它对你有所帮助。我不使用或不了解 Swift...

    就同时从 3 个文档中读取数据而言,执行此操作的方法是使用 javascript 的 .promise.all。虽然下面的代码并不完全是您的解决方案,但您可以了解如何做到这一点。

    您基本上将每个.get 推入一个数组,然后您.promise.all 那个数组.then 迭代返回的数据。

            try {
                targetRef.get().then(function(snap) {
                    if (snap.exists) {
                        for (var key in snap.data()) {
                            if (snap.data().hasOwnProperty(key)) {
                                fetchPromise = itemRef.doc(key).get();
                                fetchArray.push(fetchPromise);
                            }
                        }
                        Promise.all(fetchArray).then(function(values) {
                            populateSelectFromQueryValues(values,"order-panel-one-item-select");
                            if(!selectIsEmpty("order-panel-one-item-select")){
                                enableSelect("order-panel-one-item-select");
                            }
                        });
                    }
                }).catch(function(error) {
                    toast("error check console");
                    console.log("Error getting document:", error);
                });
            }
    

    【讨论】:

    • 我需要从所有3个文档中读取数据,我认为您不能批量读取和写入数据
    猜你喜欢
    • 2018-10-25
    • 2018-05-11
    • 2019-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多