Cloud Firestore文档获取问题:如何按指定格式返回子集合数据
嘿,我来帮你搞定这两个Firestore相关的问题!
1. 从Cloud Firestore集合/子集合获取所有文档
你当前用snapshotChanges()的思路完全没问题——这个方法能让你同时拿到文档ID和数据,非常适合你的场景。不过你的现有代码有个小疏漏:外层的map函数里没有返回document.map()生成的数组,导致最终的Observable其实不会发出正确的结果。先给你修正这个基础版本(保持数组格式):
constructor(private db: AngularFirestore) { } getAllMealDocuments() { const docRef = this.db.collection('tables').doc('documentId').collection('meals'); return docRef.snapshotChanges().pipe( map(actions => { // 这里一定要return数组结果,不然Observable会输出undefined return actions.map(doc => { return new Meal({ id: doc.payload.doc.id, ...(doc.payload.doc.data() as {}) }); }); }) ); }
如果想简化代码,也可以用valueChanges({ idField: 'id' }),它会自动把文档ID注入到数据对象里,不用手动提取:
getAllMealDocuments() { const docRef = this.db.collection('tables').doc('documentId').collection('meals'); return docRef.valueChanges({ idField: 'id' }).pipe( map(meals => meals.map(mealData => new Meal(mealData))) ); }
2. 转换为「文档ID为键,数据为值」的格式
要得到你想要的键值对格式,我们可以把map换成reduce——这个方法能帮我们把数组逐步累积成目标对象,每个文档ID作为键,对应的数据作为值。修改后的代码如下:
constructor(private db: AngularFirestore) { } getAllMealDocumentsAsKeyedObject() { const docRef = this.db.collection('tables').doc('documentId').collection('meals'); return docRef.snapshotChanges().pipe( map(actions => { // 用reduce构建键值对对象 return actions.reduce((mealMap, docAction) => { const docId = docAction.payload.doc.id; const docData = docAction.payload.doc.data() as {}; // 这里如果需要Meal实例,就把数据传入构造函数 mealMap[docId] = new Meal(docData); // 要是想把id也保留在数据里,就改成 new Meal({ id: docId, ...docData }) return mealMap; }, {} as Record<string, Meal>); // 加个类型声明,让TypeScript不报错 }) ); }
调用这个方法后,你得到的Observable会发出完全符合你期望的对象:
{ mealDocumentId1: { name: 'Burger1', imageUrl: 'imgUrl1', price: 1, quantity: 1 }, mealDocumentId2: { name: 'Burger2', imageUrl: 'imgUrl2', price: 2, quantity: 2 } }
小提示
reduce是处理这种数组转键值对场景的最优解,比手动循环构建对象更简洁。- 如果你不需要
Meal实例,直接用原始数据的话,把new Meal(docData)换成{ ...docData }就行。 Record<string, Meal>是TypeScript的类型声明,用来明确返回对象的结构,避免类型警告。
内容的提问来源于stack exchange,提问作者FabianRinortner
相关产品推荐
相关产品推荐

