Search code examples
databasefirebasegoogle-cloud-firestoremany-to-many

How to get data for a list of ids in Firestore?


I have the following relantionship of Many to Many in a Firebase Firestore Database:

Teacher (collection)
Student (collection)

A Teacher can have many students.
A Student can have many teachers.
In my database, the Teacher (collection) has a property studentIDs: [1,2,3 ... 100]

At this moment I use Array 'in' multiple times to fetch all the students data from a specified Teacher:

const studentIDs = [1,2,3..10];
const students = await userRef.where(firebase.firestore.FieldPath.documentId(), 'in', studentIDs).get();
....

The issue is that the 'in' is limitted to max 10 items, so if the Teacher has 100 Students I need to do 10 requests.

How do you solve this issue? What's the best way to get data in Firestore for a large list of documents IDs ? [1, 2, 3, 4, 5 ... 1000]


Solution

  • There is no out-of-the-box solution for your case. You have to fetch each student document one by one. Since you do all these fetches in parallel, you should use Promise.all() as follows:

      const teacherDocRef = db.collection('teachers').doc('teacher1');
    
      const teacherDoc = await teacherDocRef.get();
      const studentIDs = teacherDoc.data().studentIDs;
      
      const promises = [];
    
      studentIDs.forEach(studentID => promises.push(db.collection('students').doc(studentID).get()));
      
      const studentDocs = await Promise.all(promises);  // Array of Document Snapshots
    

    Having said that, it is quite common in NoSQL data modelling to duplicate data in order to make your queries efficient.

    If, for example, when you fetch a teacher, you only need the list of the student names (without all the data present in each student doc, e.g. without the students' address, list of courses, etc...) you could duplicate the students names in the teacher document. This is a classical approach.

    The drawback is that you need to keep in sync the different documents that hold the data (the students and teachers docs in our case). For that you can either use batched writes (from the frontend) or Cloud Functions (from the backend).