我正在使用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;
})}))
我知道架构很糟糕,“产品”应该在它自己的集合中,但是,我无法控制它:(
请帮助:)
答案 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);
}))