Tôi đang làm việc với Observables ở đây và trình bao bọc AngularFire nhưng đây là cách tôi quản lý để làm điều đó.
Thật là điên rồ, tôi vẫn đang tìm hiểu về những thứ có thể quan sát được và tôi có thể đã quá lạm dụng nó. Nhưng đó là một bài tập tốt.
Một số giải thích (không phải chuyên gia RxJS):
- songId $ là một ứng dụng có thể quan sát sẽ phát ra id
- dance $ là một hàm có thể quan sát đọc id đó và sau đó chỉ nhận giá trị đầu tiên.
- sau đó nó truy vấn CollectionGroup của tất cả các bài hát để tìm tất cả các bản sao của nó.
- Dựa trên các trường hợp mà nó truyền đến các Dances mẹ và lấy id của chúng.
- Bây giờ chúng ta có tất cả id Dance, chúng ta cần truy vấn chúng để lấy dữ liệu của chúng. Nhưng tôi muốn nó hoạt động tốt vì vậy thay vì truy vấn từng cái một, tôi gộp chúng vào nhóm 10 (góc tối đa sẽ cần cho một
in
truy vấn.
- Chúng tôi kết thúc với N nhóm và cần thực hiện N truy vấn trên firestore để nhận giá trị của chúng.
- khi chúng tôi thực hiện các truy vấn trên firestore, chúng tôi vẫn cần thực sự phân tích cú pháp dữ liệu từ đó.
- và cuối cùng chúng ta có thể hợp nhất tất cả các kết quả truy vấn để có được một mảng duy nhất với tất cả các Vũ điệu trong đó.
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();
Tôi sao chép, dán mã của mình và thay đổi tên biến thành của bạn, không chắc có lỗi nào không, nhưng nó hoạt động tốt với tôi. Hãy cho tôi biết nếu bạn tìm thấy bất kỳ lỗi nào hoặc có thể đề xuất cách tốt hơn để kiểm tra nó với một số cửa hàng firestore giả.