查询同一字段的多个Firestore集合

时间:2020-02-19 12:14:39

标签: javascript firebase google-cloud-firestore

我正在寻找多个集合中的文档,这些文档中有没有描述字段的文档,我想避免循环,但是想找到最有效的方法。该代码在一个集合中起作用。

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

1 个答案:

答案 0 :(得分:3)

您可以使用Promise.all()并行执行所有查询 ,如下所示:

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

   })

您可以将其简化如下:

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

   })

如上述文档中所述:

Promise.all()方法返回一个Promise,该Promise在以下情况下满足 通过迭代的所有诺言都已兑现

...

返回的promise由包含所有 作为参数传递的iterable的值(也包括非承诺值)。


但是,

根据您的问题中的这一句话,有一个值得注意的要点:“在多个集合中找到文档,这些文档中的文档没有描述字段”。

您无法在Firestore中建立查询,该查询将返回文档没有给定字段。在此官方video中很好地解释了原因(索引机制)。

另一方面,您可以查询具有空字段的文档:

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

或具有值为null的字段:

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