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:
At my tables service
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))
);
}
At my orders service
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$);
}
Consuming tables service at my component
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:
- I need
orders
data at the same time I gettables
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?) - I need to know when orders change at my Table component because contains a rowexpansion datatable,
table
state in the datatable is dependant oforders
state.
CodePudding user response:
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.