Как объединить несколько документов в Firestore? - PullRequest
1 голос
/ 03 августа 2020

У меня есть БД Firestore со следующей структурой:

  • пользователи

    • [uid]
      • имя: 'Пользователь один'
  • исполнители

    • [uid]
      • стиль: 'Pop teste'
      • user_uid: [uid]

в моем сервисе у меня есть

constructor(private afu: AngularFireAuth, private afs: AngularFirestore, private storage: AngularFireStorage) { 
   this.usersCollection = afs.collection<User>('users');
   this.users = this.usersCollection.valueChanges();
}

getUsers() {
   return this.users = this.usersCollection.snapshotChanges()
     .pipe(map(changes => {
       return changes.map(action => {
         const data = action.payload.doc.data() as User;
         return data
       });
     }));
 }

Как можно объединяться между пользователями и художниками?

1 Ответ

2 голосов
/ 03 августа 2020

Использование combineLatest - отличный способ. Поскольку user_uid не существует для пользователя, я добавил idField пользователю как user_uid. Сначала просмотрите код, а затем прочтите ниже для объяснения.

    import { Component, OnInit } from '@angular/core';
    import { AngularFirestore } from '@angular/fire/firestore';
    import { Observable, combineLatest } from 'rxjs';
    interface User {
      name: string;
      user_uid: string;
    }
    interface Artist {
      style: string;
      user_uid: string;
    }
    interface Joined {
      user_uid: string;
      name: string;
      style: string;
    }
    @Component({
      selector: 'test',
      templateUrl: './test.component.html',
      styleUrls: ['./test.component.scss']
    })
    export class TestComponent implements OnInit {
    
      users$: Observable<User[]>;
      artists$: Observable<Artist[]>;
      joined$: Observable<Joined[]>;
      
      constructor(private afs: AngularFirestore){}
    
      ngOnInit(){
        this.users$ = this.afs.collection<User>('users').valueChanges({idField: 'user_uid'});
        this.artists$ = this.afs.collection<Artist>('artists').valueChanges();
        this.joined$ = combineLatest(this.users$, this.artists$, (users, artists) => {
            const joinedAsMap: Map<string, Joined> = new Map(artists.map(oneArtist =>  [oneArtist.user_uid, { ...{name: null} , ...oneArtist}]));
            users.forEach(one => joinedAsMap.set(one.user_uid , {...{name: one.name}, ...joinedAsMap.get(one.user_uid) } ));
            const joined: Joined[] = Array.from(joinedAsMap.values());
            return joined;
        });
      }
    }
  1. Сделать объединенный интерфейс
  2. Получить обе наблюдаемые
  3. использовать последнюю комбинацию
  4. Создайте карту с uid в качестве ключа и исполнителем в качестве значения. Задайте для имени значение null, чтобы типы работали. Используйте оператор распространения, чтобы объединить некоторые объекты.
  5. L oop через пользователя и добавить информацию о пользователе к значению каждого ключа
  6. Создать объединенный массив из значений карты
  7. вернуть значение

Вы можете сделать это по-разному, но использование карт es6 - хороший способ упростить некоторые вещи. Кроме того, не было возможности протестировать с реальной базой данных, поэтому вам может потребоваться проверка. Кроме того, все это находится внутри компонента для демонстрации. В сервисе это точно можно было бы сделать.

...