skip to Main Content

I am looking for a more optimal way to implement the following method getting all my documents from my permits collection, than mapping company and process area data into my permit data used in a PrimeNG table.

Performance > Firebase document reads usage.

Here is my getAllPermits$() method so far:

getAllPermits$() {
    return combineLatest([
      collectionData(this.permitCollection) as Observable<any[]>, //will query this later to only show active permits
      collectionData(this.companyCollection, {idField: 'uid'}) as Observable<Company[]>,
      collectionData(this.processAreasCollection, {idField: 'uid'}) as Observable<ProcessArea[]>,
    ]).pipe(
      map(([permits, companies, processAreas]) => {
        return permits.map(permit => {
          if (permit.companyUid) {
            const company = companies.find(c => c.uid === permit.companyUid);
            if (company) {
              permit = {...permit, companyName: company?.name ?? 'Error'};
            } else {
              permit = {...permit, companyName: 'Not Found'};
            }
          } else {
            permit = {...permit, companyName: 'No Company'};
          }

          if (permit.processArea) {
            const processArea = processAreas.find(pa => pa.assetNumber === permit.processArea);
            if (processArea) {
              permit = {...permit, processAreaName: processArea?.description ?? 'Error'};
            } else {
              permit = {...permit, processAreaName: 'Not Found'};
            }
          } else {
            permit = {...permit, processAreaName: 'No Process Area'};
          }
          return permit;
        });
      })
    );
  }

Is querying single documents in the companyCollection and processAreasCollection more efficient, as opposed to mapping as shown above?

Context:
I would normally have 200 – 500 active permits (this isn’t in the code yet, but this is easy implement later).

  • companyCollection = 300+ companies where we might use 100-150 companies in the currently active permits.
  • processAreas = 160+ areas – again, we might use 50-70 areas in the actively shown permits.

I am using a big portion of the company and process area collection data, hence the question.

2

Answers


  1. faster searches could be done by using Map, then instead of .find which takes O(n) it would take you only O(1) operations for search

    const companiesMap = new Map(companies.map(c => [c.uid, c]));
    const areasMap = new Map(processAreas.map(p => [p.assetNumber, p]));
    return permits.map(permit => {
      const companyName = permit.companyUid ? companiesMap.get(permit.companyUid)?.name ||  'Not Found' : 'No Company';
      const processAreaName = ... areasMap.get(permit.processArea) ... ;
      return {
        ...permit,
        companyName,
        processAreaName,
    
      }
    })
    

    this way there shouldn’t be a problem with long remapping. But you’ll probably get some freezes during rendering large lists of data.

    Login or Signup to reply.
  2. For the best performance, move away from the relational model that you currently have, and embrace the NoSQL nature of Firestore by duplicating data.

    For example, if you duplicate the data that you need from processAreasCollection and companyCollection into each document in permitCollection, you only need to load the documents from the latter. This may seem very unnatural at first, but it’s actually key to getting great performance out of a NoSQL database like Firestore.

    If this is new to you, I recommend reading NoSQL data modeling and watching the Get to know Cloud Firestore video series.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search