Как преобразовать Observable <Observable <{...}> []> в Observable <{...} []>? - PullRequest
0 голосов
/ 26 марта 2019

Я пытаюсь объединить два наблюдаемых объекта в один наблюдаемый, чтобы я мог использовать информацию из обоих этих объектов.Оба наблюдаемых объекта - это документы из двух разных коллекций в базе данных NoSQL (база данных Cloud Firestore).Обе коллекции имеют поле с одинаковым значением (uid и partnerID).Сначала я создал запрос, чтобы получить первый наблюдаемый объект, и этот запрос возвращает Observable<{Object1}[]>.Знать, если я пытаюсь добавить код, чтобы получить второй наблюдаемый объект и объединить его с существующим, я получу Observable<Observable<{Object1 merged with Object2}>[]>.

Как я могу убедиться, что сгенерированная наблюдаемая является массивом, состоящим из объектов, которыетакое комбинация этих двух объектов, которые я извлекаю из базы данных?

Моя цель - использовать комбинированный наблюдаемый объект в моем проекте Angular.Я пытаюсь добиться этого с помощью операторов rxjs.

Это функция в моем сервисе без второго наблюдаемого объекта:

queryMatches(fieldNameOfRole, boolValueOfAccepted) {
    return this.authService.user$.pipe(
      switchMap(user => {
        return this.angularFirestore
          .collection('matches', ref => ref.where(fieldNameOfRole, '==', user ? user.uid : '')
            .where('accepted', '==', boolValueOfAccepted))
          .snapshotChanges()
          .pipe(
            map(actions => {
              return actions.map(a => {
                const data = a.payload.doc.data() as Match;
                const matchId = a.payload.doc.id;
                return { matchId, ...data };
              });
            })
          );
      })
    );
  }

Это возвращает следующий результат:

(method) MatchStoreService.queryMatches(fieldNameOfRole: any, boolValueOfAccepted: any): Observable<{
    initiatorID: string;
    partnerID: string;
    matchedOffer: string;
    accepted: boolean;
    id: string;
}[]>

И вот как я пыталсяобъединить его со вторым наблюдаемым объектом:

queryMatches(fieldNameOfRole, boolValueOfAccepted) {
    return this.authService.user$.pipe(
      switchMap(user => {
        return this.angularFirestore
          .collection('matches', ref => ref.where(fieldNameOfRole, '==', user ? user.uid : '')
            .where('accepted', '==', boolValueOfAccepted))
          .snapshotChanges()
          .pipe(
            map(actions => {
              return actions.map(a => {
                const data = a.payload.doc.data() as Match;
                const matchId = a.payload.doc.id;
                return { matchId, ...data };
              });
            })
          );
      }),
      map(matches => {
        return matches.map(match => {
          return this.userStoreService.getUserById(match.partnerID).pipe(
            map(user => {
              return { ...match, ...user };
            })
          );
        });
      })
    );
  }

Это приведет к следующему возвращению:

(method) MatchStoreService.queryMatches(fieldNameOfRole: any, boolValueOfAccepted: any): Observable<Observable<{
    uid: string;
    firstname: string;
    lastname: string;
    dateOfBirth: Date;
    sex: string;
    city: string;
    activities: string[];
    offers: string[];
    mail?: string;
    ... 4 more ...;
    matchId: string;
}>[]>

UPDATE

Как я реализовал getUserById ():

getUserById(uid) {
    return this.angularFirestore
    .collection<any>(`users`)
    .doc<User>(uid).valueChanges();
   }

1 Ответ

1 голос
/ 26 марта 2019

просто используйте оператор forkJoin как этот

 map(matches => {
        return combineLatest(matches.map(match => {
          return this.userStoreService.getUserById(match.partnerID).pipe(
            map(user => {
              return { ...match, ...user };
            })
          );
        }));
      })
...