当我运行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 )?
还有另一种方法可以解决这个问题吗?
答案 0 :(得分: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 }
正在使用do catch block
范围之外的doc1
,doc2
进行操作
答案 1 :(得分:0)
我刚刚注意到你正在使用Apple的快速脚本。我的答案是基于标准的JavaScript,但我希望它能帮到你。我不会使用或了解有关Swift的任何信息......
至于同时从3个文档中读取数据,这样做的方法是使用javascript' s .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);
});
}