sleepz
sleepz

Reputation: 33

Use SnapshotChanges with CombineLatest

I'm using combineLatest to merge 3 different query from Firestore. However, I don't want to use valueChanges(), I want to use snapshotChanges().

const newRef = this.afs.collection('applications', ref => ref.orderBy('date_created_at', 'desc').where('status', '==', 'new')).snapshotChanges().pipe(
  map(changes => {
    return changes.map(a => {
      const data = a.payload.doc.data() as Application;
      const id = a.payload.doc.id;
      return {id, ...data};
    })
  })
);

const pendingRef = this.afs.collection('applications', ref => ref.orderBy('date_created_at', 'desc').where('status', '==', 'pending')).snapshotChanges().pipe(
  map(changes => {
    return changes.map(a => {
      const data = a.payload.doc.data() as Application;
      const id = a.payload.doc.id;
      return {id, ...data};
    })
  })
);

const inprogressRef = this.afs.collection('applications', ref => ref.orderBy('date_created_at', 'desc').where('status', '==', 'in-progress')).snapshotChanges().pipe(
  map(changes => {
    return changes.map(a => {
      const data = a.payload.doc.data() as Application;
      const id = a.payload.doc.id;
      return {id, ...data};
    })
  })
);

const result = combineLatest<any[]>(newRef, pendingRef, inprogressRef).pipe(
  map(arr => arr.reduce((acc, cur) => acc.concat(cur)))
);
return result;

How do I merge these 3 queries to get their respective document id? Do I have to write the 3 queries this way or is there any other way? I want to simplify the codes.

Upvotes: 1

Views: 286

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 598728

There are many approaches to reduce the code.

A very simple one...

Define a function to do the work:

function processChanges(changes) {
    return changes.map(a => {
      const data = a.payload.doc.data() as Application;
      const id = a.payload.doc.id;
      return {id, ...data};
    })
}

And then use it 3 times:

const newRef = this.afs.collection('applications', ref => ref.orderBy('date_created_at', 'desc').where('status', '==', 'new')).snapshotChanges().pipe(map(processChanges)));

const pendingRef = this.afs.collection('applications', ref => ref.orderBy('date_created_at', 'desc').where('status', '==', 'pending')).snapshotChanges().pipe(map(processChanges)));

const inprogressRef = this.afs.collection('applications', ref => ref.orderBy('date_created_at', 'desc').where('status', '==', 'in-progress')).snapshotChanges().pipe(map(processChanges)));

const result = combineLatest<any[]>(newRef, pendingRef, inprogressRef).pipe(
  map(arr => arr.reduce((acc, cur) => acc.concat(cur)))
);
return result;

Alternatively define a helper function and call that thrice:

function getApplicationsForStatus(status) {

return this.afs.collection('applications', ref => ref.orderBy('date_created_at', 'desc').where('status', '==', status)).snapshotChanges().pipe(
  map(changes => {
    return changes.map(a => {
      const data = a.payload.doc.data() as Application;
      const id = a.payload.doc.id;
      return {id, ...data};
    })
  })
);

And use it as:

const newRef = getApplicationsForStatus('new');
const pendingRef = getApplicationsForStatus('pending'); 
const inprogressRef = getApplicationsForStatus('progress');

const result = combineLatest<any[]>(newRef, pendingRef, inprogressRef).pipe(
  map(arr => arr.reduce((acc, cur) => acc.concat(cur)))
);
return result;

Upvotes: 1

Related Questions