2

I'm working on some project with AngularFire + FireStore.

My Firestore model looks like this:

  • Collection 1

    • key1 {some data}
    • key2 {some data}
  • Collection 2

    • key1 {other data}
    • key2 {other data}

Now I need to show list where I have some data from the first collection, and some data from another one. How to create such a list?

It seems to be pointless to make two observables and then merge it.

const collection = this.afStore.collection<any>(collectionName);
    return collection.snapshotChanges()
      .map(participants => {
        return participants.map(participant => {
          const data = participant.payload.doc.data();
          const id = participant.payload.doc.id;
          return {id, ...data};
        });
      });
      

I have this code that takes data + id, and now I need to use this id to pull data from another collection, but don't know how.

4 Answers4

6

Here's how I did mine...

The "projects" data has customer_doc_id, customer_builder_doc_id, customer_contractor_doc_id, which are doc_id of other data collections in Firestore. The command mergeMap works in rxjs^5.5.0.

 private getProjectsCombineObservables(): Observable<any[]> {
this.projectsCollection = this.afs.collection<Project>('projects', ref =>
  ref.orderBy('job_number', 'desc'));
return this.projectsCollection.snapshotChanges()
  .map(actions => {
    return actions.map(a => {
      const project_data = a.payload.doc.data() as Project;
      const doc_id = a.payload.doc.id;

      let observable1 = this.getCustomer(project_data.customer_doc_id);
      let observable2 = this.getBuilder(project_data.customer_builder_doc_id);
      let observable3 = this.getContractor(project_data.customer_contractor_doc_id);

      const combinedData = Observable.combineLatest(observable1, observable2, observable3, (data1, data2, data3) => {
        return { ...data1, ...data2, ...data3 };
      });

      return combinedData.map(data => Object.assign({}, { doc_id, ...project_data, ...data }));
    });
  }).mergeMap(observables => Observable.combineLatest(observables));

}

Joe
  • 75
  • 2
  • 5
  • 2
    sorry, but you can't just throw methods around without explaining where they came from. What is this.getCustomer()? What is this.getBuilder()? Where did they come from? What are they doing? – Olu Adeyemo Aug 22 '18 at 10:09
1

Wohoo! I did it :)

So it should be like this:

const collection = this.afStore.collection<any>('collection1');
    return collection.snapshotChanges()
      .map(participants => {
        return participants.map(participant => {
          const data = participant.payload.doc.data();
          const id = participant.payload.doc.id;
          return this.afStore.doc('collection2/' + id).valueChanges()
            .map(data2 => Object.assign({}, {id, ...data, ...data2}));
        });
      }).flatMap(observables => Observable.combineLatest(observables));
1

const collection = this.afStore.collection<any>('collection1');
    return collection.snapshotChanges()
      .map(participants => {
        return participants.map(participant => {
          const data = participant.payload.doc.data();
          const id = participant.payload.doc.id;
          return this.afStore.doc('collection2/' + id).valueChanges()
            .map(data2 => Object.assign({}, {id, ...data, ...data2}));
        });
      }).flatMap(observables => Observable.combineLatest(observables));
  • I tried this code but is return a observable of observable. how can I get the data. When I do a subscribe it return a array of observable. – Miguel Peguero Dec 05 '18 at 21:45
  • 2
    you should not post your issue as an answer. Instead comment to the respected answer. – Anuj TBE Mar 09 '19 at 02:54
1

After trying multiple solution I get it done with RXJS combineLatest, take operator. Using map function we can combine result.

combineLatest(
    this.fireBaseService.getFromCollection1(),
    this.fireBaseService.getFromCollection2(),
    //In collection 2 we have document with reference id of collection 1
)
.pipe(
    take(1),
).subscribe(
    ([dataFromCollection1, dataFromCollection2]) => {

        this.dataofCollection1 = dataFromCollection1.map((data) => {
            return {
                id: data.payload.doc.id,
                ...data.payload.doc.data() as {},
            }
            as IdataFromCollection1;
        });

        this.dataofCollection2 = dataFromCollection2.map((data2) => {
            return {
                id: data2.payload.doc.id,
                ...data2.payload.doc.data() as {},
            }
            as IdataFromCollection2;
        });

        console.log(this.dataofCollection2, 'all feeess');

        const mergeDataFromCollection =
            this.dataofCollection1.map(itm => ({
                payment: [this.dataofCollection2.find((item) => (item.RefId === itm.id))],
                ...itm
            }))

        console.log(mergeDataFromCollection, 'all data');
    },