Ich arbeite hier mit Observables und dem AngularFire- Wrapper, aber so habe ich das geschafft.
Es ist irgendwie verrückt, ich lerne immer noch über Observable und habe es möglicherweise übertrieben. Aber es war eine schöne Übung.
Einige Erklärungen (kein RxJS-Experte):
- songId $ ist ein Observable, das IDs ausgibt
- dance $ ist ein Observable, das diese ID liest und dann nur den ersten Wert erhält.
- Anschließend wird die Sammlungsgruppe aller Songs abgefragt, um alle Instanzen davon zu finden.
- Basierend auf den Instanzen werden die übergeordneten Tänze durchlaufen und ihre IDs abgerufen.
- Nachdem wir alle Dance-IDs haben, müssen wir sie abfragen, um ihre Daten zu erhalten. Aber ich wollte, dass es gut funktioniert, und anstatt sie einzeln
in
abzufragen, staple ich sie in Eimern von 10 (der maximale Winkel wird für eine Abfrage benötigt.
- Wir haben am Ende N Buckets und müssen N Abfragen im Firestore durchführen, um ihre Werte zu erhalten.
- Sobald wir die Abfragen im Firestore durchgeführt haben, müssen wir die Daten daraus tatsächlich analysieren.
- und schließlich können wir alle Abfrageergebnisse zusammenführen, um ein einziges Array mit allen darin enthaltenen Tänzen zu erhalten.
type Song = {id: string, name: string};
type Dance = {id: string, name: string, songs: Song[]};
const songId$: Observable<Song> = new Observable();
const dance$ = songId$.pipe(
take(1), // Only take 1 song name
switchMap( v =>
// Query across collectionGroup to get all instances.
this.db.collectionGroup('songs', ref =>
ref.where('id', '==', v.id)).get()
),
switchMap( v => {
// map the Song to the parent Dance, return the Dance ids
const obs: string[] = [];
v.docs.forEach(docRef => {
// We invoke parent twice to go from doc->collection->doc
obs.push(docRef.ref.parent.parent.id);
});
// Because we return an array here this one emit becomes N
return obs;
}),
// Firebase IN support up to 10 values so we partition the data to query the Dances
bufferCount(10),
mergeMap( v => { // query every partition in parallel
return this.db.collection('dances', ref => {
return ref.where( firebase.firestore.FieldPath.documentId(), 'in', v);
}).get();
}),
switchMap( v => {
// Almost there now just need to extract the data from the QuerySnapshots
const obs: Dance[] = [];
v.docs.forEach(docRef => {
obs.push({
...docRef.data(),
id: docRef.id
} as Dance);
});
return of(obs);
}),
// And finally we reduce the docs fetched into a single array.
reduce((acc, value) => acc.concat(value), []),
);
const parentDances = await dance$.toPromise();
Ich habe meinen Code kopiert und die Variablennamen in Ihre geändert. Ich bin mir nicht sicher, ob es Fehler gibt, aber es hat gut funktioniert. Lassen Sie mich wissen, wenn Sie Fehler finden oder einen besseren Weg vorschlagen, um sie mit einem nachgebildeten Firestore zu testen.