Цепные угловые коллекции Firestore - PullRequest
0 голосов
/ 03 февраля 2019

Это сложно объяснить, но я сделаю все возможное.У меня есть структура базы данных в Firebase, например:

Пользователь (пользователь Firebase)

  • Электронная почта

Соединение

  • Электронная почта
  • Группа
  • Роль

UserDetails

  • Электронная почта
  • Имя
  • Фамилия
  • Адрес

По сути, я пытаюсь получить текущего пользователя с помощью AngularFireAuth, затем запросить коллекцию сведений о пользователе с помощью user.email, а затем запросить коллекцию Connectionsпо user.email.Наконец, сопоставьте все это модели User и сохраните ее в наблюдаемой.

РЕДАКТИРОВАТЬ:

Я выяснил, как получить первую коллекцию для наблюдаемого пользователем, но не уверен, гдеиди отсюда.

    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 ]

0 голосов
/ 05 февраля 2019

Итак, после некоторого исследования я пришел к этому решению, которое работает.Вероятно, не самый лучший подход, но для проекта проверки концепции у меня все в порядке.

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 };
    })
) 
0 голосов
/ 03 февраля 2019

Мой первоначальный подход к этому состоял бы в том, чтобы создать 2 отдельные наблюдаемые для пользовательских данных и соединения, а затем использовать combLatest для получения полного профиля пользователя:

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

Дополнительные примеры использования combLatest:

Learn Rxjs

...