Это трудно объяснить, но я постараюсь. У меня есть настройка структуры базы данных в Firebase следующим образом:
Пользователь (пользователь Firebase)
Связь
Детали пользователя
По сути, я пытаюсь получить текущего пользователя с помощью AngularFireAuth, затем запросить коллекцию сведений о пользователе с помощью user.email, а затем запросить коллекцию Connections с помощью 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 отдельных наблюдаемых для сведений о пользователе и соединении, а затем использовать 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:
Хм, я бы проверил, исходит ли канал authState сначала, выполнив выход пользователя из системы. Затем проверьте в базе данных, есть ли какой-либо действительный адрес электронной почты, связанный с этим пользователем.
вы также можете использовать для этого forkJoin. forkJoin будет выдавать значения только тогда, когда все наблюдаемые генерируют хотя бы одно значение
Итак, после некоторых исследований я придумал это решение, которое действительно работает. Вероятно, это не лучший подход, но для экспериментального проекта меня это устраивает.
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 };
})
)
Я пробовал это именно так, как вы предложили, но мне не удалось заставить это успешно работать. Наблюдаемые объекты connectionCollection$ и userDetailsCollection$ остаются неопределенными, что действительно странно.