Search code examples
angulartypescriptgoogle-cloud-firestorerxjsangularfire

Performing two firebase queries with argument from first query at once (inner join) using operators?


To select document im using this function:

reservations: observable<any>;

/// ...
    this.reservations = this.afs.collection('reservations', ref => ref.where('uid', '==', 'someUID'))
      .snapshotChanges()
      .pipe(
        map(reservationData => {
          return reservationData.map(reservation => {
            const data = reservation.payload.doc.data();
            const id = reservation.payload.doc.id;

            console.log(data);

            return { id, ...data };
          });
        })
      );

in result i got:

[
    "serviceid": "TM2Y6vBk70rgKZ3zTUAw",
    "uid": "MwdM8bak78eE1omf6u04KtqlE2X2",
    "venueid": "9G0miVLclY7QBZcHAMuq"
  },
  {
    "serviceid": "dReNKvOyV1rOussdSdNe",
    "uid": "MwdM8bak78eE1omf6u04KtqlE2X2",
    "venueid": "2l3NhWeTC2HfB6nJmo5X"
  }
]

How to add another query to this obervable? It should be working like inner join in sql, i need to add document from services collection (from received serviceid). This function should return:

[
  {
    "rOussk78eE1oMwdM8ba": [
      {
        "name": "some name",
        "price": 142
      }
    ],
    "uid": "MwdM8bak78eE1omf6u04KtqlE2X2",
    "venueid": "9G0miVLclY7QBZcHAMuq"
  },
  {
    "dReNKvOyV1rOussdSdNe": [
      {
        "name": "some name",
        "price": 142
      }
    ],
    "uid": "MwdM8bak78eE1omf6u04KtqlE2X2",
    "venueid": "2l3NhWeTC2HfB6nJmo5X"
  }
]

How can i do this?


Thanks in advance,
D.

Solution

  • this.reservations = this.afs
          .collection('reservations', ref => ref.where('uid', '==', 'someUID'))
          .snapshotChanges()
          .pipe(
            map(reservationData =>
              reservationData.map(reservation => ({
                id: reservation.payload.doc.id,
                data: reservation.payload.doc.data()
              }))
            ),
            switchMap(reservationArr => from(reservationArr)), // reduce the mapped array to single observables
            switchMap(reservation =>
              this.afs
                .collection(`services`, ref => ref.where('serviceID', '==', reservation.id))
                .valueChanges()
                .pipe(
                  map(serviceData => {
                    const data = {};
                    data[reservation.id] = serviceData;
                    return { data, ...reservation };
                  })
                )
            )
          );
    

    you can add a switchMap after you get your data to switch to your second query, and pipe > map that observable to rebuild your data with the original reservationData (called reservation) and your second query's serviceData.