Ad

Chaining Angular Firestore Collections

This is hard to explain but I'll do my best. I have a database structure setup in Firebase like this:

User (Firebase User)

  • Email

Connection

  • Email
  • Group
  • Role

UserDetails

  • Email
  • First Name
  • Last Name
  • Address

Basically what I am trying to do is get the current user using AngularFireAuth, then query the User Details collection by user.email, and then query the Connections collection by user.email. Finally, map all this out to a User model and store that in an observable.

EDIT:

I have figured out how to get the first collection to the user observable but not sure where to go from here.

    this.user = this.afAuth.authState.pipe(
        map(user => user.email),
        flatMap(email => this.afs.collection<User>(this.userRef, res => res.where('email', '==', email)).valueChanges()),
        mergeAll(),
        first()
    )

EDIT2:

So this is what I came up with and it's working BUT it just seems not right. I can tell there is a performance impact (albeit not that much). Probably won't ever use this for production but I'll continue using this solution as a proof of concept until I can find a better way.

    this.user = this.afAuth.authState.pipe(
        map(user => user.email),
        concatMap(email => {
            return zip(
                this.afs.collection<Connection>('connections', res => res.where('email', '==', email)).snapshotChanges().pipe(mergeAll(), first()), 
                this.afs.collection<User>('users', res => res.where('email', '==', email)).snapshotChanges().pipe(mergeAll(), first())
            )
        }),
        map(([connection, details]) => {
            const a = connection.payload.doc.data() as Connection;
            const b = details.payload.doc.data() as User;
            return { ...a, ...b };
        })
    ) 
Ad

Answer

So after some research, I came up with this solution which does work. Probably not the best approach, but for a proof-of-concept project I am okay with it.

this.user = this.afAuth.authState.pipe(
    map(user => user.email),
    concatMap(email => {
        return zip(
            this.afs.collection<Connection>('connections', res => res.where('email', '==', email)).snapshotChanges().pipe(mergeAll(), first()), 
            this.afs.collection<User>('users', res => res.where('email', '==', email)).snapshotChanges().pipe(mergeAll(), first())
        )
    }),
    map(([connection, details]) => {
        const a = connection.payload.doc.data() as Connection;
        const b = details.payload.doc.data() as User;
        return { ...a, ...b };
    })
) 
Ad
source: stackoverflow.com
Ad