子节点的angularfire集合平面图

时间:2018-10-09 12:34:03

标签: angular rxjs google-cloud-firestore

我正在使用Angular和Google FireStore存储“订单”列表。每个订单都有“产品”列表。我如何才能从可完全满足我们查询的所有“订单”中展平单个可观察产品阵列?

数据如下:

[
{
  id: "item1",
  products: [
    { product1... }, {product2... }
  ]
},
{
  id: "item2",
  products: [
    { product3...}, {product2... }
  ]
}
]

最终结果应为可观察到的产品列表:

[{product1...}, {product2...}, {product3...}, {product2...}]

我尝试使用flatMap,但无法使其与AngularFire查询结果一起正常使用。我当前的“试用”效果相当好,并且确实给出了“产品”列表。问题在于它只有最后一个“订单”中的“产品”。

这就是我现在拥有的:

return this.db.collection<Order>('orders', ref => ref.where('status', '==', 3))
  .snapshotChanges()
  .pipe(
    flatMap(orders=> {
      return orders.map(a => {
          const order = a.payload.doc.data() as Order;
          return order.products;
        })}))

我知道架构很糟糕,“产品”应该在它自己的集合中,但是,我无法控制它:(

请帮助:)

4 个答案:

答案 0 :(得分:0)

如果您使用map而不是flatMap怎么办?

flatMap需要一个返回ObservableInput的函数作为参数。数组IS和ObservableInput,在这种情况下,flatMap转换Observable中的数组,该数组发出数组中的每个项目。

因此您的代码

flatMap(orders=> {
  return orders.map(a => {
      const order = a.payload.doc.data() as Order;
      return order.products;
    })}))

返回一个Observable,它发出orders集合的每个项目作为单独的通知。

如果您想要一个Observable发出一个产品列表,即发出一个数组,那么您可以将flatMap替换为map

答案 1 :(得分:0)

这是使用reduce的方法。

const myArrayOfArrays = [
  [{id: 1, name: 'a'}, {id: 2, name: 'b'}, {id: 3, name: 'c'}],
  [{id: 10, name: 'x'}, {id: 20, name: 'y'}, {id: 30, name: 'z'}],
  [{id: 100, name: 'ax'}, {id: 200, name: 'by'}, {id: 300, name: 'cz'}],
]
of(myArrayOfArrays).pipe(
  map(myArrayOfArrays => myArrayOfArrays
    .reduce(
      (acc, val) => acc.concat(val), []
    ))
)
.subscribe(console.log)

答案 2 :(得分:0)

不使用flatMap(和管道),请尝试以下操作:

  return this.db.collection<Order>('orders', ref => 
                ref.where('status', '==', 3))
        .snapshotChanges()
        .map(orders => {
           return orders.map(a => {
                  const order = a.payload.doc.data() as Order;
                 return order;
                 });
           })
        .mergeMap(p => from(p.products));

答案 3 :(得分:0)

谢谢大家的时间和精力,我真的很感激。

这就是我最终得到的结果,可悲的是它并没有“感觉”正确,但是可以。

flatMap(orders=> {
 let products = [];
 orders.map(a => {
  const order = a.payload.doc.data() as Order;
  order.products.map(product => products.push(product));
 })
 return of(products);
}))