skip to Main Content

I want to update the field code in all the documents of a collection. Since it takes multiple write operations, I want to update the collection altogether.

This is the code (used batched writes as given in the documentation) :

const batch = writeBatch(db);
const userRef = doc(db, "users", userId)
const repoRef = doc(userRef, "repos", repo)
const filesRef= collection(repoRef, "files")

batch.update(filesRef, data);

The data object:

{
    README: {languageId: 45, code: 'slkjf', name: 'README'}
    main: {languageId: 62, name: 'main', code: 'haah'}
}

Error:

No error shown

What is the solution and is this the best method, or should I use a map method and recursively update the field in every document?

2

Answers


  1. If you want to update all documents inside a collection so first you’ll need to get all documents of this collection:

    import { collection, query, where, getDocs, writeBatch,   } from "firebase/firestore";
    
    const querySnapshot = await getDocs(
      query(collection(db, `users/${userId}/repos`))
    )
    
    

    Then you’ll need to loop through all these documents and add the change to batch:

    const batch = writeBatch(db)
    querySnapshot.forEach((doc) => {
      const docRef = doc(db, `users/${userId}/repos/${doc.id}`)
      batch.update(docRef, {
        field: "Changed value"
      })
    })
    
    // write your changes
    await batch.commit()
    

    You can find more about this here.

    Hope this helps

    Login or Signup to reply.
  2. The first parameter of a call to WriteBatch#update() is a DocumentReference. In your code you instead try to pass in a CollectionReference.

    To write the code property of each entry in a given object to your database, you first must iterate through the object and add update operations into your batch before committing it to the server.

    For the given object and references:

    const data = {
        README: { languageId: 45, code: 'slkjf', name: 'README' },
        main: { languageId: 62, code: 'haah', name: 'main' }
    }
    
    const userDocRef = doc(db, "users", userId);
    const repoDocRef = doc(userDocRef, "repos", repo);
    const repoFilesColRef = collection(repoDocRef, "files");
    
    const batch = writeBatch(db);
    

    You can add update operations into the batch like so:

    for (let [docId, fileData] of Object.entries(data)) {
      batch.update(
        doc(repoFilesColRef, docId),
        { code: fileData.code }
      );
    };
    

    Once you are ready to apply the changes to the server, call the commit method and handle the returned Promise object.

    batch.commit()
      .then(() => console.log("updates successful"))
      .catch((err) => console.error("updates failed", err));
    

    Batched writes have a limit of 500 operations per batch, so to handle that you can use this function to automatically create more batches as needed.

    Note: Atomic updates are not guaranteed across multiple batches, only for each individual batch.

    function multiWriteBatch(db) {
      let batch = writeBatch(db), batches = [batch], size = 0;
    
      const getBatch = () => {
        if (++size >= 500) {
          // start new batch
          batch = writeBatch(db);
          size = 0;
          batches.push(batch);
        }
        return batch;
      }
    
      return {
        commit: () => Promise.all(batches.map(b => b.commit())),
        delete: (ref) => getBatch().delete(ref),
        set: (...args) => getBatch().set(...args),
        update: (...args) => getBatch().update(...args)
      }
    }
    
    // usage:
    const batch = multiWriteBatch(db);
    // fill as normal
    batch.commit()
      .then(() => console.log("all batches successful"))
      .catch((err) => console.error("one or more batches failed", err));
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search