我正在尝试在一个Firestore事务中运行多个文档更新,我想知道这是否是反模式。
我有一个名为“ Group”的文档,其中包含一个名为“ members”的数组,其中包含与用户集合不同的ID。现在,我想遍历所有成员并在一笔交易中更新相应的用户文档。这可能吗?
我尝试使用.forEach()遍历所有成员,但问题是据我所知,.forEach()不支持异步/等待或使用Promise。
答案 0 :(得分:1)
以下应该可以解决问题:
var firestore = firebase.firestore();
//.....
var groupDocRef = firestore.doc('collectionRef/docRef');
return firestore
.runTransaction(function(transaction) {
var arrayOfMemberIds;
return transaction
.get(groupDocRef)
.then(function(groupDoc) {
if (!groupDoc.exists) {
throw 'Group document does not exist!';
}
arrayOfMemberIds = groupDoc.data().members;
return transaction.update(groupDocRef, {
lastUpdate: firebase.firestore.FieldValue.serverTimestamp()
});
})
.then(function() {
arrayOfMemberIds.forEach(function(memberId) {
transaction = transaction.update(
firestore.collection('users').doc(memberId),
{ foo: 'bar' }
);
});
return transaction;
});
});
这将起作用,因为update()
方法返回了可用于链接方法调用的Transaction实例。
还请注意,我们必须更新初始的groupDoc
。否则,将引发以下错误:FirebaseError: "Every document read in a transaction must also be written."
。在上面的示例中,我们仅使用时间戳更新了lastUpdate
字段。由您决定要执行的更新!
您可以通过如下设置一些安全规则来轻松测试此代码的事务性方面:
service cloud.firestore {
match /databases/{database}/documents {
match /collectionRef/{doc} {
allow read: if true;
}
match /users/{user} {
allow read: if false;
}
}
}
由于无法写入users
集合,因此Transaction
将失败并且collectionRef/docRef
文档将不被更新。
测试事务方面的另一种(甚至更好的)方法是删除users
文档之一。由于update()
方法如果应用于不存在的文档会失败,因此整个Transaction
将失败。