链接 Angular 个 Firestore 集合

Chaining Angular Firestore Collections

这很难解释,但我会尽力而为。我在 Firebase 中设置了这样的数据库结构:

用户(Firebase 用户)

连接

用户详细信息

基本上我想做的是使用 AngularFireAuth 获取当前用户,然后通过 user.email 查询用户详细信息集合,然后通过 user.email 查询连接集合。最后,将所有这些映射到用户模型并将其存储在可观察对象中。

编辑:

我已经想出如何让用户可观察到第一个集合,但不确定从这里去哪里。

    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()
    )

编辑 2:

这就是我想出的方法,它正在运行,但它似乎不正确。我可以说这对性能有影响(尽管影响不大)。可能永远不会将其用于生产,但我会继续使用此解决方案作为概念证明,直到找到更好的方法。

    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 };
        })
    ) 

我最初的做法是为用户详细信息和连接创建 2 个单独的可观察对象,然后使用 combineLatest 获取完整的用户配置文件:

import { combineLatest } from 'rxjs';

let connectionCollection$: Observable<DocumentChangeAction<T>[]>
let userDetailsCollection$: Observable<DocumentChangeAction<T>[]>
let user: UserModel;


this.afAuth.authState.pipe(
        map(user => user.email),
        tap(email => {
            this.connectionCollection$ = this.afs.collection('connection', res => res.where('email', '==', email)).snapshotChanges()
            this.userDetailsCollection$ = this.afs.collection('userdetails', res => res.where('email', '==', email)).snapshotChanges() 
        }
)

combineLatest(connectionCollection$, userDetailsCollection$).subscribe(
    ([connection, userDetails]) => {
        //map the result to the user object e.g user.grandma = connection.grandma
    }
)

使用 combineLatest 的更多示例:

Learn Rxjs

经过一番研究,我想出了这个可行的解决方案。可能不是最好的方法,但对于概念验证项目,我可以接受。

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 };
    })
)