Search code examples
javascriptangularfirebasegoogle-cloud-firestoreangularfire2

How to make a query that retrieve a collection and a subcollection in firebase with angularfire?


I've the following structure in my firebase DB:

/profiles/{uid}/displayName
               /email
               /otherAttribues
               /roles/{roleName}/someAttribute
                                /someOtherAttribute

So "roles" is a subcollection, mostly because it has to have different writes rights than the rest of the profile.

In my component, I currently retrieve the profiles:

  constructor(private firestore: AngularFirestore) {
    this.users$ = this.firestore.collection<User>('profiles').valueChanges();
  }

In my html, I'm using this users$ in a *ngFor loop to display the profiles in the grid. I need to add one column that will be shown based on the presence/absence of a role with the ID "admin" or "user". This can be modified from other users, so it has to be an observable.

How can I retrieve the "roles" of my profile(at least the IDs of the documents in the subcollection) and still iterate on them nicely?

This can change, so I need this to be an observable. I cannot find a way to "include" a subcollection in my request.

And based on the roles, I need to have


Solution

  • I've done the following in my user component:

    this.users$ = this.firestore.collection<User>('profiles').valueChanges({ idField: 'uid' }).pipe(
          switchMap((profiles) => {
            const res = profiles.map(profile => {
              return this.firestore.collection(`profiles/${profile.uid}/roles`).valueChanges({ idField: 'Id' }).pipe(
                map(doc => {
                  return doc.map(d => d.Id)
                }),
                tap(roles => {
                  //TODO: consolidate the profile with the roles here
                  //This will be updated on changes
                }),
                map(roles => Object.assign(profile, { roles }))
              );
            })
            return combineLatest(...res);
          })
        );
    

    Note: it warns me about the deprecation of combineLatest, but not sure how to replace it.