Pooya Panahandeh
Pooya Panahandeh

Reputation: 638

iterate through multiple document with certain doc id from a collection

hope you are coding well, I am using firebase and vue js to build a messenger application. Each user has a document, and within each document there is a field named includeInMsg, which contains the Id of the message that the user included. I know how to read one document by its id, but I don't know how to read multiple documents by their ids. here you can see my code:

import { ref } from "vue";
import { db } from "src/boot/firebase";
import { getAuth, onAuthStateChanged } from "firebase/auth";
import { updateDoc, arrayUnion, arrayRemove } from "firebase/firestore";
import {
  addDoc,
  collection,
  query,
  where,
  getDocs,
  getDoc
} from "firebase/firestore";
import { doc, onSnapshot } from "firebase/firestore";

export default {
  setup() {
    return {
      userList: ref([]),
      userMessageRefList: ref([]),
      userMessageDocList: ref([]),
      freelancerProfile: ref([]),
      messages: ref([]),
      userMessage: ref([]),
      listofdata: ref([])
    };
  },
  async created() {
    // check if user loged in or not
    const auth = getAuth();
    onAuthStateChanged(auth, user => {
      if (user) {
        // store current user uid in userlist
        this.userList.unshift(user.uid);
        this.renderMessageList();
      } else {
        this.$router.push("/");
      }
    });
  },
  methods: {
    // render user message list doc id
    async renderMessageList() {
      const currentUserProfile = query(
        collection(db, "userProfile"),
        where("uuid", "==", this.userList[0])
      );
      const userProfileQuerySnapshot = await getDocs(currentUserProfile);
      userProfileQuerySnapshot.forEach(doc => {
        let docData = doc.data();
        this.userMessageRefList.unshift(docData.messageList);
        this.listofdata.unshift(docData);
      });
      this.userMessageRefList.forEach(elem =>
        // store doc id into userMessageDocList
        elem.forEach(le => this.userMessageDocList.unshift(le))
      );
      console.log(this.userMessageDocList) //output: {0: {…}, 1: {…}}
      // now I need to read each document by their doc Id and store it in an array to render

    },
  },
  computed: {
    checkMessages: function() {
      if (this.messages.length > 1) {
        return true;
      } else {
        return false;
      }
    }
  }
};

I tried to use for loop to read each document and store the value in an array but I got SyntaxError: Unexpected reserved word 'await'. (71:26) error.

Upvotes: 0

Views: 717

Answers (1)

Renaud Tarnec
Renaud Tarnec

Reputation: 83048

As confirmed in the comments, this.userMessageDocList contains a compounded object containing objects with the documents IDs.

In this case you should use Promise.all() to trigger a variable number of calls to Firestore in parallel.

As explained in the doc (see link above):

The Promise.all() method takes an iterable of promises as an input, and returns a single Promise that resolves to an array of the results of the input promises.


So you need to loop over the object, grab the Docs IDs and populate an Array of Promises that you pass to Promise.all(). In pseudo code (I let you use the method you want to loop over the object, there are a lot of examples on SO) it's something along the following lines:

const promisesArray = [];

<Loop For each element>
   // Assumption: element.docId contains the Firestore doc ID
   promisesArray.push(getDoc(doc(db, "yourCollection", element.docId)))

</End Loop>

const docSnapshotsArray = await Promise.all(promisesArray);
docSnapshotsArray.forEach(docSnap => {
   console.log(docSnap.data());
   // ...
});

docSnapshotsArrays is an Array of DocumentSnapshots. You can then loop over this array and do whatever you want.


I don't now if this is important for your specific case, but note that with Promise.all(), the returned values in the resulting Array will be in order of the Promises passed, regardless of completion order.

Upvotes: 2

Related Questions