skip to Main Content

Let me say I have ‘teacher’ collection inside ‘teacher’ collection I have ‘student’ collection in Firebase, I need to display every student of every teacher in a list.
I know I can create separate student collection linking teacher id, but this is the scenario I need to work with.
Please help me how can I get every student using FirebaseFirestore query.

3

Answers


  1. To achieve this you will query all the teachers and then all the students inside each teacher. I have implemented so I am sharing my experience with you.
    First of all make two models TeacherModel and StudentModel with json serialization for your ease. I have created dummy models you can add your fields in models.

    class TeacherModel {
      TeacherModel({
        this.students,
      });
    
      factory TeacherModel.fromJson(Map<String, dynamic> json) {
        /// implement from json
        return TeacherModel(students: []);
      }
    
      /// all the properties of teacher
      List<StudentModel>? students;
    
      Map<String, dynamic> toJson() => {};
    }
    
    class StudentModel {
      StudentModel();
    
      /// all the properties of student
      factory StudentModel.fromJson(Map<String, dynamic> json) {
        return StudentModel();
      }
    
      Map<String, dynamic> toJson() => {};
    }
    

    After creating models you have two options.

    1- Get all data in a stream as following.

      static Stream<List<TeacherModel>> getStreamData() async* {
        final firestore = FirebaseFirestore.instance;
        var allTeachers = <TeacherModel>[];
        final result = firestore.collection('teachers').snapshots();
        await for (final r in result) {
          final teacherDocs = r.docs;
          for (final teacherDoc in teacherDocs) {
            final students = (await firestore
                    .collection('teachers/${teacherDoc.id}/students')
                    .get())
                .docs
                .map((e) => StudentModel.fromJson(e.data()))
                .toList();
            final teacher = TeacherModel.fromJson(teacherDoc.data());
            teacher.students = students;
            allTeachers.add(teacher);
            yield allTeachers;
          }
        }
      }
    

    2- Get all data in future as following.

    static Future<List<TeacherModel>> getFutureData() async {
        final firestore = FirebaseFirestore.instance;
        var allTeachers = <TeacherModel>[];
        final result = (await firestore.collection('teachers').get()).docs;
        for (final r in result) {
          final students =
              (await firestore.collection('teachers/${r.id}/students').get())
                  .docs
                  .map((e) => StudentModel.fromJson(e.data()))
                  .toList();
          final teacher = TeacherModel.fromJson(r.data());
          teacher.students = students;
          allTeachers.add(teacher);
        }
        return allTeachers;
      }
    
    Login or Signup to reply.
  2. What you’re looking for is known as a collection group query, which allows you to read/query documents from all collections with a specific name.

    Based on the documentation:

    db
        .collectionGroup("student")
        .get()
        .then(
          (res) => print("Successfully completed"),
          onError: (e) => print("Error completing: $e"),
        );
    
    Login or Signup to reply.
  3. I was researching a solution and you have to get creative like how @Sparko recoommends. In the firestore docs they say this:

    "The listCollections() method of the Cloud Firestore server client libraries lists all subcollections of a document reference.

    Retrieving a list of collections is not possible with the mobile/web client libraries. You should only look up collection names as part of administrative tasks in trusted server environments. If you find that you need this capability in the mobile/web client libraries, consider restructuring your data so that subcollection names are predictable."

    This is also a possible work around

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search