Having a parent collection tables
with documents which each one have a collection named orders
. I want to subscribe to tables and listen to orders changes. What I tried:
watchTables(): Observable<any> {
return this.afStore
.collection('restaurants')
.doc(this.rid)
.collection('tables')
.snapshotChanges()
.pipe(
map((data: any) =>
data.map((documentDataTable: any) => ({
id: documentDataTable.payload.doc.id,
...documentDataTable.payload.doc.data()
}))
.sort((a: any, b: any) => a.number - b.number)
),
mergeMap((tables: any) => this.ordersService.watchOrders(tables))
);
}
watchOrders(tables: any): Observable<any> {
let orders$: Observable<any>[] = [];
tables.forEach((table: any) =>
orders$.push(
this.afStore
.collection('restaurants')
.doc(this.rid)
.collection('tables')
.doc(table.id)
.collection('orders')
.snapshotChanges()
.pipe(
map((data: any) => {
return data.map((documentDataOrder: any) => ({
id: documentDataOrder.payload.doc.id,
...documentDataOrder.payload.doc.data()
}))
.sort((a: any, b: any) => this.sortOrders(a, b))
})
).pipe(
map(data => ({ table: table, orders: data }))
)
));
return zip(orders$);
}
subscribeToTables() {
this.tablesService
.watchTables()
.subscribe((collectedTablesData: any) => {
console.log('table or orders changed');
});
}
I thougth about desestructuring data, but couldn't find an answer myself. Or I'm just messing with Observables, probably both.
Things I need in the solution:
orders
data at the same time I get tables
data(thats why in first place I thought orders would be part of table doc as an array of maps, but isn't that overkill?)table
state in the datatable is dependant of orders
state.As you seem to have gather already, there is no way to listen to parent documents and their child collections at once. Reads and listens in Firestore are shallow, and only cover one collection or all collections with a certain name.
You have a few options:
You can include a field in the table document that indicates the state of its orders. At its simplest this could be a ordersLastUpdatedAt
timestamp field, but you could also have a list of order IDs and the timestamp of their individual most recently updates. Either way, you should update the field(s) in the table document whenever a relevant order is updated too, and then use that as a trigger in your client to (re)load the orders for the table.
You can also use a collection group query on orders
at the path of the table document, as Sam showed in his answer to CollectionGroupQuery but limit search to subcollections under a particular document.