Chaddeus
Chaddeus

Reputation: 13356

How to Update All Documents in a Collection With Thousands of Documents in FireStore with Firebase Admin?

Updated to reflect Firebase-Admin, rather than v9 New Update: solution at the bottom

How to update a single field (in a map) for all documents in a collection with thousands of documents -- in firebase-admin/firestore (10.0.2)? I attempted to use this:

import { getFirestore } from 'firebase-admin/firestore'
const db = getFirestore()

db.collection("users").get().then(function(querySnapshot) {
  querySnapshot.forEach(function(doc) {
    doc.ref.update({
        "words.subscription": 0
    })
  })
})

I use it within a Node.js (v12) cloud function. The function runs, I see no errors, but none of the documents are updated. Previously, I attempted to use set() because some documents may not have the field, but Frank let me know update() can update fields that don't exist too.

However, this updated code also does not update all the documents in the 'users' collection.

Thank you in advance.

Update/Solution @Dharmara - thank you for the gist. It did not work as-is, so I decided to change to async/await and wrap it in try/catch (to hopefully find out why it wasn't working), like so:

try {
  let querySnapshot = await db.collection('users').get()

  if (querySnapshot.size === 0) {
    console.log('No documents to update')
    return 'No documents to update'
  }

  const batches: any[] = [] // hold batches to update at once

  querySnapshot.docs.forEach((doc, i) => {
    if (i % 500 === 0) {
      batches.push(db.batch())
    }

    const batch = batches[batches.length - 1]
    batch.update(doc.ref, { "words.subscription": 0 })
  })

  await Promise.all(batches.map(batch => batch.commit()))
  console.log(`${querySnapshot.size} documents updated`)
  return `${querySnapshot.size} documents updated`
}
catch (error) {
  console.log(`***ERROR: ${error}`)
  return error
}

When I tested this however, it worked. From what I can tell it's the same as the then() way you had in the gist (and from what I had found elsewhere in SO).

If you wanted to put this into an answer I'd gladly mark it as the answer. Your code helped tremendously. Thank you.

Upvotes: 2

Views: 1305

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 598708

The dot notation you use to write a nested field only works when you call update(), not for set(). Luckily update() works for non-existing fields, it only requires that the document already exists.

So for the namespaced API of v8 and before that'd be:

doc.ref.update({
  "words.subscription": 0
})

For the modular API for v9 and beyond, it's:

update(doc.ref, {
  "words.subscription": 0
})

Upvotes: 2

Related Questions