ฉันกำลังทำงานกับ Observables ที่นี่และAngularFire wrapper แต่นี่คือวิธีที่ฉันจัดการได้
มันบ้ามากฉันยังคงเรียนรู้เกี่ยวกับสิ่งที่สังเกตได้และฉันอาจจะทำมากเกินไป แต่มันเป็นการออกกำลังกายที่ดี
คำอธิบายบางส่วน (ไม่ใช่ผู้เชี่ยวชาญ RxJS):
- songId $ เป็นสิ่งที่สังเกตได้ซึ่งจะปล่อยรหัสออกมา
- dance $ เป็นค่าที่สังเกตได้ซึ่งอ่าน id นั้นแล้วรับเฉพาะค่าแรกเท่านั้น
- จากนั้นจะค้นหา collectionGroup ของเพลงทั้งหมดเพื่อค้นหาอินสแตนซ์ทั้งหมดของมัน
- ขึ้นอยู่กับอินสแตนซ์ที่ข้ามไปยัง Dances หลักและรับรหัสของพวกเขา
- ตอนนี้เรามีรหัส Dance ทั้งหมดแล้วเราจำเป็นต้องค้นหาเพื่อรับข้อมูล แต่ฉันต้องการให้มันทำงานได้ดีดังนั้นแทนที่จะค้นหาทีละรายการฉันจัดกลุ่มเป็นกลุ่ม 10 (ค่าเชิงมุมสูงสุดจะใช้ในการ
in
สืบค้น
- เราจบลงด้วย N ที่เก็บข้อมูลและจำเป็นต้องทำ N แบบสอบถามบน firestore เพื่อรับค่าของพวกเขา
- เมื่อเราทำแบบสอบถามบน firestore เรายังคงต้องแยกวิเคราะห์ข้อมูลจากสิ่งนั้น
- และในที่สุดเราก็สามารถรวมผลลัพธ์การค้นหาทั้งหมดเพื่อให้ได้อาร์เรย์เดียวกับ Dances ทั้งหมดในนั้น
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();
ฉันคัดลอกวางรหัสของฉันและเปลี่ยนชื่อตัวแปรเป็นของคุณไม่แน่ใจว่ามีข้อผิดพลาดหรือไม่ แต่ก็ใช้ได้ดีสำหรับฉัน แจ้งให้เราทราบหากคุณพบข้อผิดพลาดใด ๆ หรือสามารถแนะนำวิธีที่ดีกว่าในการทดสอบกับ Firestore จำลอง