Combine multiple Firestore database collection calls results in a single array

236 Views Asked by At

After successfully getting all references for a sub-collection that i'm using for subsequent db calls i'm trying to combine results in a single array of Observables.

Right now the value inside subscription of the loadAllLessons() function updates to a single array each time a lesson reference is being parsed and a db query using snapshotChanges() made on.

The targeted sub-collection(Lessons) inside Firestore's db is nested inside a collection(courses). My code looks pretty much like this:

 getAllLessonsRef(): Observable<string[]> {
    return this.db.collection('/courses')
      .snapshotChanges()

      .pipe(map(snap => snap.map(s => {
        const courseId = s.payload.doc.id;

        const lessonRef = `/courses/${courseId}/lessons`;

        return lessonRef

      })));

  }

  loadAllLessons(): Observable<any> {
    
    return this.getAllLessonsRef()
    
      .pipe(switchMap(lessonRefs => {

        let items =
          lessonRefs.map(ref => {
            console.log(ref)
            return this.db.collection(`${ref}`).snapshotChanges()
          });

         return merge(...items)
      }),
      
       map(list => {
        return convertSnaps<Lesson>(list)
      }))
  }

What would be the best approach to combine all subsequent results?

2

There are 2 best solutions below

0
On

The solution I found on this using my old code was to join the results within the subscribe method

    this.lessonService.loadAllLessons()
      .subscribe(
          lessons => {
            lessons.map(lesson => {
                this.allLessons.push(lesson)
            })
          }
        )
1
On

I would maybe use a forkJoin for this. More about forkJoin here.

  import { forkJoin } from 'rxjs';
....
  loadAllLessons(): Observable<any> {
    
    return this.getAllLessonsRef()
    
      .pipe(switchMap(lessonRefs => {
        return forkJoin(...lessonRefs.map(ref => this.db.collection(`${ref)`).snapshotChanges()));
      }),
      
       map(list => {
        return convertSnaps<Lesson>(list)
      }))
  }