Phill Duffy
Phill Duffy

Reputation: 2866

Query multiple Firestore Collections for same field

I am looking to find documents across several Collections where they have documents with no description field, I want to avoid looping but want to find the most efficient way of doing this. This code works in one collection.

            firebase
            .firestore()
            .collection('creators') // ### Would need to loop for 4 others like this #####
            .where('description', '==', '')
            .get()
            .then((snapshot) => {
                if (snapshot.empty) {
                    console.log('No matching documents.')
                    return
                }

                snapshot.forEach((doc) => {
                    console.log(doc.id, '=>', doc.data())
                })
            })
            .catch((err) => {
                console.log('Error getting documents', err)
            })

Upvotes: 0

Views: 472

Answers (1)

Renaud Tarnec
Renaud Tarnec

Reputation: 83048

You could use Promise.all() to execute all the queries in parallel, as follows:

   const db = firebase.firestore();

   const q1 = db.collection('creators').where('description', '==', '...').get();
   const q2 = db.collection('xyz').where('description', '==', '...').get();

   return Promise.all([q1, q2])
   .then(snapshotsArray => {

       snapshotsArray.forEach(snap => {
            snap.forEach(doc => {
                console.log(doc.id, '=>', doc.data())
            })
       })

   })

You could simplify it as follows:

   const collectionNames = ['creators', 'klmn', 'opqr', 'stuv']
   const promises = collectionNames.map(x => db.collection(x).where('description', '==', '...').get());

   Promise.all(promises)
   .then(snapshotsArray => {

       snapshotsArray.forEach(snap => {
            snap.forEach(doc => {
                 console.log(doc.id, '=>', doc.data())
            })
       })

   })

As explained in the doc referred to above:

The Promise.all() method returns a single Promise that fulfills when all of the promises passed as an iterable have been fulfilled

...

The returned promise is fulfilled with an array containing all the values of the iterable passed as argument (also non-promise values).


HOWEVER,

there is an important point to note, based on this sentence in your question: "find documents across several Collections where they have documents with no description field".

You cannot build a query in Firestore that will return document without a given field. The reason (indexing mechanism) is well explained in this official video .

On the other hand, you can query for a document with an empty field:

db.collection('creators').where('description', '==', '').get();

or with a field with null value:

db.collection('creators').where('description', '==', null).get();

Upvotes: 3

Related Questions