简体   繁体   中英

Firestore transaction update multiple collections in a single transaction

How can i update multiple collections in firestore by using a single transaction i searched but i didn't get any answers. Is it possible to update multiple collections in a single transaction?

I want to update branch.name at-once in classroom & students collection 在此处输入图片说明

在此处输入图片说明

As explained in the documentation for the Node.js Client Library update() method, it returns a Transaction which is " used for chaining method calls ." (Note that update() method of the Admin SDK behaves exactly the same way).

So, for example, if within the transaction you want to get a value from a classroom doc, increase it and use it to update two documents from two different collections ( classrooms and students ), you would do as follows:

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);
});

Note that if you need to do several reads before your multiple updates, "when using transactions, read operations must come before write operations ."


On the other hand, IF YOU JUST WANT TO UPDATE multiple documents WITHOUT READING one or more values (you say in your question that you "want to update branch.name at-once in classroom & students collection "), you don't need to use a transaction. Just use a batched write , as follows:

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 () {
  // ...
});

UPDATE Following your comments

In your Cloud Function, you can very well chain different Firestore queries (with where() ) and in each then() populate the batch and then in the last then() commit the batch. See below for an example (just adapt with the correct queries):

 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); });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM