Firestore交易在单个交易中更新多个集合

时间:2019-08-26 07:14:17

标签: node.js firebase google-cloud-firestore google-cloud-functions

我如何使用搜索到的单个交易更新Firestore中的多个集合,但没有得到任何答案。可以在一次交易中更新多个集合吗?

我想一次更新 branch.name ,以收集课堂和学生的信息 enter image description here

enter image description here

1 个答案:

答案 0 :(得分:2)

如Node.js客户端库update()方法的文档中所述,它返回Transaction,它是“ 用于链接方法调用”。 (请注意,Admin SDK的update()方法的行为方式完全相同。)

例如,如果您想在交易中从课堂文档中获取价值,请增加它并使用它来更新来自两个不同集合(classroomsstudents)的两个文档,您将执行以下操作:

const db = firebase.firestore();  //or admin.firestore() in a Cloud Function
const docRef1 = db.collection('classrooms').doc('classroomDocId');
const docRef2 = db.collection('students').doc('studentDocId');


let transaction = db.runTransaction(t => {
  let newNumericValue;
  return t.get(docRef1 )
    .then(doc => {
      newNumericValue = doc.data().numericValue + 1;  //You calculate the new value
      return t.update(docRef1 , {numericValue : newNumericValue});
    }).then(t => {
      return t.update(docRef2 , {numericValue : newNumericValue});
    });
}).then(result => {
  console.log('Transaction success!' + result);
}).catch(err => {
  console.log('Transaction failure:', err);
});

请注意,如果您需要在多次更新之前进行多次读取,则“在使用事务时,读取操作必须先于写入操作。”


另一方面,如果您只想更新多个文档,不读一个或多个值(您在问题中说“您想更新分支”。在教室和学生集合中一次命名”),则无需使用交易。只需使用batched write,如下所示:

let batch = db.batch();

let cRef = db.collection('classrooms').doc('classroomDocId');
batch.set(cRef, {branch.name: 'newName'});

let sRef = db.collection('students').doc('studentDocId');
batch.update(sRef, {branch.name: 'newName'});

return batch.commit().then(function () {
  // ...
});

更新您的评论

在您的Cloud Function中,您可以很好地链接不同的Firestore查询(使用where()),并在每个then()中填充批次,然后在最后一个then()中提交该批次。参见下面的示例(只需使用正确的查询即可):

 let batch = admin.firestore().batch();

 return admin.firestore().collection('students').where('branch.id', '==', documentId).get()
 .then((querySnapshot) => {
    querySnapshot.forEach((doc) => { 
        batch.update(doc.ref, {branch: {id: documentId, name: after.name}}); 
    });
    return admin.firestore().collection('student_public').where('branch.id', '==', documentId).get();
 })
 .then((querySnapshot) => {
    querySnapshot.forEach((doc) => { 
        batch.update(doc.ref, {branch: {id: documentId, name: after.name}}); 
    });
    return batch.commit() 
 })
 .catch(err => { console.log('error===>', err); });