Sb Zakaria
Sb Zakaria

Reputation: 369

How to join 2 lists in Angular firebase

I spent the last 2 hours searching for a solution, and oddly enough, didn't find any. I have worked with sql and nosql databases before but never encountered such a problem. My problem is simple and clear. I have 2 collections : Raw materials & Raw materials stock. Each raw material stock document contains a raw material key. what i want is to the raw material data by its key and join it to the raw material stock list. For eg Raw materials Stock document looks like this

{
    "factoryKey": "34",
    "quantity": "34",
    //  i want to get this raw material key data such as name...etc
    "rawMaterialKey": "-NDNPe47CDTbjmwGgW_3"
}

Raw material document looks like the following

{
    "key": "-NDNPe47CDTbjmwGgW_3"
    "code": "R34",
    "name": "RAW2001"
}

here's my angular code

import {Injectable, OnInit} from '@angular/core';
import {LocalStoreService} from '../local-store.service';
import {AngularFirestore} from '@angular/fire/compat/firestore';
import {Router} from '@angular/router';
import { RawMaterialStock } from '../../interfaces/raw-materials/raw-materiels-stock';
import {AngularFireDatabase, AngularFireList, AngularFireObject } from '@angular/fire/compat/database';
@Injectable({
  providedIn: 'root',
})
export class RawMaterialsStockService implements OnInit {

  rawMaterialsStocksRef: AngularFireList<any>;
  rawMaterialsRef: AngularFireList<any>;
  rawMaterialStockRef: AngularFireObject<any>;

  private dbPathStock = '/raw_material_stock';
  private dbPathRawMaterials = '/raw_material';

  constructor(
    private store: LocalStoreService,
    private router: Router,
    private afs: AngularFirestore,
    private db: AngularFireDatabase
  ) {

    this.rawMaterialsStocksRef = db.list(this.dbPathStock);
    this.rawMaterialsRef = db.list(this.dbPathRawMaterials);
  }

  ngOnInit(): void {
  }
  // Methods
  getRawMaterialStockList() {
    return this.rawMaterialsStocksRef.snapshotChanges(['child_added'])
      .subscribe(actions => {
        // WHAT SHOULD I DO HERE ????
      });
  }
}

Please help me out i' stuck with that problem. i didn't understand any article solving that problem !

Upvotes: 0

Views: 119

Answers (1)

Lim Shang Yi
Lim Shang Yi

Reputation: 111

Since snapshotChanges on AngularFire are Observables, you can take advantage of rxjs to help combine them into 1. You will need to combine both the snapshotChanges of rawMaterialsStockref and rawMaterialsRef.

Here's the steps:

  1. Query the raw material_stock collection.
  2. Once the stock is received, query a raw_material document based on the rawMaterialKey field
  3. Combine it with the raw_material_stock into an object.
  4. Finally emit the object as an Observable stream

Sample code:

this.rawMaterialsStockref =
      firestore.collection<any>('raw_material_stock');
    this.rawMaterialsRef = firestore.collection<any>('raw_material');

    this.rawMaterialsStockref
      .snapshotChanges(['added'])
      .pipe(
        switchMap((stockSnapshots) => {
          const stockWithRawMaterialsObservables = stockSnapshots.map((s) => {
            const stockId = s.payload.doc.id;
            const stock = s.payload.doc.data();

            return this.rawMaterialsRef
              .doc(stock.rawMaterialKey)
              .snapshotChanges()
              .pipe(
                map((rawMaterialSnapshot) => {
                  const rawMaterial = rawMaterialSnapshot.payload.data() ?? {};

                  return { ...rawMaterial, ...stock };
                })
              );
          });

          return combineLatest(stockWithRawMaterialsObservables);
        })
      )
      .subscribe((stocks) => {
        stocks.forEach((s) => console.log(s));
      });

Upvotes: 1

Related Questions