Saya bekerja dengan Observables di sini dan bungkus AngularFire tetapi inilah cara saya berhasil melakukannya.
Agak gila, saya masih belajar tentang yang bisa diamati dan saya mungkin melebih-lebihkannya. Tapi itu latihan yang bagus.
Beberapa penjelasan (bukan ahli RxJS):
- songId $ adalah observable yang akan memancarkan id
- dance $ adalah observable yang membaca id itu dan kemudian hanya mendapatkan nilai pertama.
- itu kemudian menanyakan collectionGroup dari semua lagu untuk menemukan semua contohnya.
- Berdasarkan contoh itu melintasi ke tarian induk dan mendapatkan id mereka.
- Sekarang kita memiliki semua ID Dance yang kita butuhkan untuk menanyakannya untuk mendapatkan datanya. Tapi saya ingin itu bekerja dengan baik jadi alih-alih menanyakan satu per satu, saya menumpuknya dalam ember 10 (sudut maksimum akan mengambil
in
kueri.
- Kami berakhir dengan N keranjang dan perlu melakukan kueri N di firestore untuk mendapatkan nilainya.
- setelah kami melakukan kueri di firestore, kami masih perlu benar-benar mengurai datanya.
- dan akhirnya kita bisa menggabungkan semua hasil query untuk mendapatkan array tunggal dengan semua tarian di dalamnya.
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();
Saya menyalin menempelkan kode saya dan mengubah nama variabel menjadi milik Anda, tidak yakin apakah ada kesalahan, tetapi itu berfungsi dengan baik untuk saya. Beri tahu saya jika Anda menemukan kesalahan atau dapat menyarankan cara yang lebih baik untuk mengujinya dengan mungkin beberapa firestore tiruan.