Reputation: 170
I know this has been asked before but I can't figure out my scenario from the typical answers provided. In my app I have firebase collection called objectives and a tasks collection that have a one to many relationship. Each objective has a tasks array (filled with the ID's of the tasks) and each task has an objectiveId. I would like to join these so when I make a snapshotChanges() call to get all objectives I would like to return an array of objectives with tasks objects nested in.
I have this code and I know it does not work cuz I can't return something in an observable but I was wondering how would I use RxJS operators in this case?
loadObjectives() {
return this.objectivesCollection.snapshotChanges().pipe(
map(actions => {
return actions.map(_ => {
const id = _.payload.doc.id;
const data = _.payload.doc.data();
const tasks = this.afs
.collection<Task>("tasks", ref =>
ref.where("objectiveId", "==", id)
)
.valueChanges().subscribe( tasks => {
return new Objective(id, data.title, tasks);
});
});
}),
tap(objectives => {
this._objectives.next(objectives);
})
);}
Upvotes: 1
Views: 679
Reputation: 9308
It can be done with some clever RxJS code, but it's often easier to join data by passing props between components. For example, read your objectives first, then pass the ID down to a child to run another query for tasks.
<objectives-list *ngFor="let obj of objectivesCollection | async">
<tasks-list [objective]="obj">
But to answer your question, the code below will start with objectives, then map each result to a query of tasks. The final result will be an array of arrays (tasks collections).
this.objectivesCollection.valueChanges({idField: 'id'}).pipe(
switchMap(objectives => {
// map each objective to a task query
const joins = objectives.map(obj => this.afs
.collection<Task>("tasks", ref => ref.where("objectiveId", "==", obj.id))
.valueChanges()
)
// execute all queries concurrently with combineLatest.
return combineLatest(joins)
})
)
Upvotes: 1