Объедините запрос с Angularfire2 и firestore - PullRequest
0 голосов
/ 15 мая 2018

Спасибо за чтение.

У меня есть две коллекции в Firestore, и я использую Angularfire2.

У меня есть коллекции "Clients" и коллекция "Jobs".У клиентов может быть несколько заданий, и у каждого задания есть связанный клиент.

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

Вот мои данные:

Client list

Jobs list

Мне удалось «взломать» решение, но оно чрезвычайно глючное, и оно теряет всю асинхронность - так что я мог бы также написать бэкэнд MySQL и забыть о Firestore - весь смысл использования Firestore заключается в том, что это"жить".

    public jobs = {};
[...]       
    processData() {

            const clients = [];
             this.clientCollection.ref.get().then((results) => {
              results.forEach((doc) => {
                clients[doc.id] = doc.data();
              });
              const jobs = {};
              this.jobsCollection.ref.get().then((docSnaps) => {
                docSnaps.forEach((doc) => {
                  jobs[doc.id] = doc.data();
                  jobs[doc.id].id = doc.id;
                  jobs[doc.id].clientData = clients[doc.data().client];
                });
                this.jobs = jobs;
              });

            });

          }

Это работает до некоторой степени - но это устраняет асинхронность.

Ключевой вопрос: есть ли способ сделать "соединение", как мы бы вБаза данных SQL, чтобы объединить эти два набора данных?И есть ли способ сделать это так, чтобы сохранить асинхронный характер данных?

1 Ответ

0 голосов
/ 16 мая 2018

Вы можете попытаться использовать Promise.all() для извлечения нескольких обещаний в один объект. Вот пересмотренная версия вашего метода, которая должна дать желаемый результат, если я правильно понимаю ваш вопрос:

  async processData() {
    const clientCollection = await firebase.firestore().collection(`clients`).get();
    const jobsCollection = await firebase.firestore().collection(`jobs`).get();
    const clients = [];
    clients.push(clientCollection);
    clients.push(jobsCollection);
    const res = await Promise.all(clients);
    // res should equal a combination of both querySnapshots
  }

Я просто пересоздал переменные коллекции, чтобы показать, что добавить в массив, но Promise.all() принимает массив обещаний и разрешает их все в один массив, так как метод get() в firestore является обещанием. Это также использует async / await. Надеюсь, это поможет!

EDIT:

Поскольку вы используете AngularFire2, вы должны использовать их метод для этого.

В вашем компоненте вы захотите импортировать модуль angularfire2/firestore и использовать предоставляемые ими методы Observable:

Сначала импортируйте модуль: import { AngularFireStore } from 'angularfire2/firestore';

затем предоставьте это вашему конструктору:

  constructor(
    private firestore: AngularFireStore
  ) { }

Тогда вы можете использовать Observable.combineLatest() для получения всех данных за один раз:

  clients$: Observable<any[]>;
  clients: any[];

  jobs$: Observable<any[]>;
  jobs: any;

  joined: any;

  ngOnInit() {
    this.clients$ = this.getCollection('clients');
    this.jobs$ = this.getCollection('jobs');
    this.joined = Observable.combineLatest(this.clients$, this.jobs$);
    this.joined.subscribe(([clients, jobs]) => {
      this.clients = clients;
      this.jobs = jobs;
    });
  }


  getCollection(collectionName) {
    return this.firestore.collection(`${collectionName}`).valueChanges();
  }

В вашей разметке вы просто зациклите данные, используя *ngFor:

<div *ngFor="let client of clients">{{ client.name }}</div>

Таким образом, ваш компонент будет прослушивать новые данные, как только Firestore получит данные, и все они появятся за один раз, поэтому у вас нет вложенных подписок, уязвимых для создания нескольких подписок. Надеюсь, что это может помочь.

...