Map items of collection snapshot in Firebase Firestore

Viewed 38146

Firebase Firestore Guides show how to iterate documents in a collection snapshot with forEach:

db.collection("cities").get().then(function(querySnapshot) {
    querySnapshot.forEach(function(doc) {
        console.log(doc.id, " => ", doc.data());
    });
});

I imagined it would support map as well, but it doesn't. How can I map the snapshot?

6 Answers

The answer is:

querySnapshot.docs.map(function(doc) {
  # do something
})

The Reference page for Firestore reveals the docs property on the snapshot.

docs non-null Array of non-null firebase.firestore.DocumentSnapshot

An array of all the documents in the QuerySnapshot.

Got pretty sick and tired of Firestore returning stuff in their classes or whatever. Here's a helper that if you give it a db and collection it will return all the records in that collection as a promise that resolves an actual array.

const docsArr = (db, collection) => {
  return db
    .collection(collection)
    .get()
    .then(snapshot => snapshot.docs.map(x => x.data()))
}

;(async () => {
  const arr = await docsArr(myDb, myCollection)
  console.log(arr)
})()
// https://firebase.google.com/docs/firestore/query-data/get-data
const querySnapshot = await db.collection("students").get();

// https://firebase.google.com/docs/reference/js/firebase.firestore.QuerySnapshot?authuser=0#docs
querySnapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() }));

Here's another example

var favEventIds = ["abc", "123"];

const modifiedEvents = eventListSnapshot.docs.map(function (doc) {
    const eventData = doc.data()
    eventData.id = doc.id
    eventData.is_favorite = favEventIds.includes(doc.id)

    return eventData
})

I have found that a better way to do this by using map and get your document id as well is as follows:

start with the object array I wish to update in your constructor:

    this.state = {
                allmystuffData: [
                {id: null,LO_Name: "name", LO_Birthday: {seconds: 0, nanoseconds: 0},    
                LO_Gender: "Gender", LO_Avatar: "https://someimage", LO_Type: "xxxxx"},],
    };

and in my function do the following

    const profile = firebase
        .firestore()
        .collection("users")
        .doc(user.uid)
        .collection("stuff")
        .get()
        .then( async (querySnapshot) => {
            console.log("number of stuff records for ",user.uid," record count is: ", 
            querySnapshot.size);
            const profile = await Promise.all(querySnapshot.docs.map( async (doc) => {
                const stuffData = doc.data()
                stuffData.id = doc.id
                condole.log("doc.id => ",doc.id)
                return stuffData
        }));
    
        this.setState({allmystuffData: profile});
        })
        .catch(function (error) {
            console.log("error getting stuff: ", error);
        })

In this example I read all the documents in the collection with querysnapshot the when mapping accross them. the promise.all ensures that all the records are returned before you render it to your screen. I add the document id to the "id" element of each object in the array returned, then I use setstate to replace my state array with the array returned from the query.

you can try this

FirebaseFirestore.instance
  .collection('Video_Requests')
  .get()
  .then((QuerySnapshot querySnapshot){querySnapshot.docs.forEach((doc){
    print(doc.data());
   });
});
Related