在 Angularfire2 中合并集合和子集合可观察对象

Merging collection and sub collection observables in Angularfire2

我已将 stripe 集成到我的 firebase 项目 (Firestore) 中,该项目通过网络挂钩将我在 Stripe 中设置的产品添加和更新到 firestore 数据库。为了显示可用产品,我有一个使用异步管道在模板中订阅的可观察对象。这一切都很好,但是,产品集合中的每个产品文档都有一个名为 'prices' 的子集合,其中包含当前和以前的价格。我正在尝试弄清楚如何 return 可观察到的主要产品中每个产品的附加数据。

return 产品的代码是:


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

  watchProducts () {

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

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

模板代码为:

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

价格集合的位置是:

this._firestore
.collection('products')
.doc({productId})
.collection('prices', ref => {
        return ref.where('active', '==', true);
      })

我想合并结果,以便在异步 ngFor 中我可以使用 active === true 访问当前价格。我看过 switchMap 和 mergeMap 但似乎无法正常工作。我的知识是 RxJs 有点有限。

如有任何帮助,我们将不胜感激。

最佳 A

您可以创建自己的 operator 作为 Jeff introduced。但为了简化,您可以按以下方式管理它:

const products$ = this._firestore
  .collection('products')
  .snapshotChanges()
  .pipe(
    map((actions: any[]) => actions.map((a) => ({ ...a.payload.doc.data(), ...{ id: a.payload.doc.id } }))),
    switchMap((products: any[]) => {
      const pricesCols$ = products.map((p) =>
        this._firestore
          .collection(`products/${p.id}/prices`, (ref) => ref.where('active', '==', true))
          .valueChanges()
      );

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