Merging collection and sub collection observables in Angularfire2


I have integrated stripe into my firebase project (Firestore) which through web hooks adds and updates the products I have setup in Stripe to the firestore database. To display available products I have an observable which is subscribed in the template using async pipe. This all works fine, however, each product document in the products collection has a sub collection called ‘prices’ which contains the current and previous prices. I am trying to figure out how to return this additional data for each product in the main products observable.

The code to return just the products is:

export interface Item { name: string; id: string; }

  watchProducts () {

      const productsCollection: AngularFirestoreCollection<Item> =
      .collection('products', ref => {
        return ref.where('active', '==', true);

      const currentProducts: Observable<Item[]> = productsCollection.snapshotChanges().pipe(
        map(actions => actions
          .map(a => {
            const data =;
            const id =;
            return { id, };
      return currentProducts;

The template code is:

            <button *ngFor="let product of products | async" ">
                {{}} £/ month

The location of the prices collection is:

.collection('prices', ref => {
        return ref.where('active', '==', true);

I would like to merge the results so in the async ngFor I could access the current price with active === true. I’ve looked at switchMap and mergeMap but can’t seem to get anything to work properly. My knowledge is RxJs is somewhat limited.

Any help would be greatly appreciated.

Best A


You can create your own operator as Jeff introduced. But to simplify, you could manage it as following way:

const products$ = this._firestore
    map((actions: any[]) => => ({, ...{ id: } }))),
    switchMap((products: any[]) => {
      const pricesCols$ = =>
          .collection(`products/${}/prices`, (ref) => ref.where('active', '==', true))

      // passing the products value down the chain
      return combineLatest([of(products), combineLatest(pricesCols$.length ? pricesCols$ : [of([])])]);
    map(([products, pricesCols]) =>, idx) => {
        p.prices = pricesCols[idx];
        return p;

Answered By – coturiv

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published