Angular Firebase:从AngularFirestore获取单个对象失败求助
问题分析与解决方案
核心问题
你的getById()方法逻辑有误:你用where('id', '==', estateId)查询集合,但Firestore的文档ID(doc id)并不是文档内部的默认字段——除非你在创建文档时手动把ID存入了id字段,否则这个查询会返回空数组。另外,获取单个文档不需要用集合查询,直接通过文档ID定位即可。
修正步骤
1. 修复EstateService的getById方法
将原来返回集合的逻辑改为直接获取单个文档,返回AngularFirestoreDocument<Estate>或者封装好的Observable:
import { Injectable } from '@angular/core'; import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument, } from '@angular/fire/compat/firestore'; import { Estate } from '../models/estate.model'; import { Observable, map } from 'rxjs'; @Injectable({ providedIn: 'root', }) export class EstateService { private dbPath = '/estates'; estatesRef: AngularFirestoreCollection<Estate>; constructor(private db: AngularFirestore) { this.estatesRef = db.collection(this.dbPath); } // 其他方法保持不变... // 修正后的getById:直接定位单个文档 getById(estateId: string): AngularFirestoreDocument<Estate> { return this.estatesRef.doc(estateId); } // 可选:直接返回包含文档ID的Observable,简化组件逻辑 getByIdWithId(estateId: string): Observable<Estate | undefined> { return this.estatesRef.doc(estateId).snapshotChanges().pipe( map(doc => { if (!doc.payload.exists) return undefined; return { ...doc.payload.data() as Estate, id: doc.payload.id }; }) ); } }
2. 修正EstateDetailsComponent的fetchSingleEstate方法
适配新的服务方法,直接处理单个文档:
import { Component, OnInit, OnDestroy } from '@angular/core'; import { Estate } from '../models/estate.model'; import { EstateService } from '../services/estate.service'; import { ActivatedRoute } from '@angular/router'; import { Subscription } from 'rxjs'; @Component({ selector: 'app-estate-details', templateUrl: './estate-details.component.html', styleUrls: ['./estate-details.component.scss'], }) export class EstateDetailsComponent implements OnInit, OnDestroy { estate: Estate | undefined; private subscription?: Subscription; constructor( private estateService: EstateService, private activatedRoute: ActivatedRoute ) {} ngOnInit(): void { this.fetchSingleEstate(); } fetchSingleEstate(): void { this.estate = undefined; const estateId = this.activatedRoute.snapshot.params['id']; // 方式1:使用返回AngularFirestoreDocument的方法 this.subscription = this.estateService.getById(estateId).snapshotChanges().pipe( map(doc => { if (!doc.payload.exists) return undefined; return { ...doc.payload.data() as Estate, id: doc.payload.id }; }) ).subscribe(data => { this.estate = data; console.log(data); }); // 方式2:用封装好的getByIdWithId方法(更简洁) // this.subscription = this.estateService.getByIdWithId(estateId).subscribe(data => { // this.estate = data; // console.log(data); // }); } // 销毁订阅避免内存泄漏 ngOnDestroy(): void { this.subscription?.unsubscribe(); } }
额外排查点(若需用where查询id字段)
如果你是手动在文档中存储了id字段(比如创建时把doc id存入文档内部),需检查:
- Firestore控制台中,目标文档是否真的存在
id字段,且字段值与路由参数的estateId完全一致(注意大小写、空格) - 字段类型是否匹配(比如都是字符串,避免数字与字符串类型不匹配)
内容的提问来源于stack exchange,提问作者Radoslav Hadzhiev
相关产品推荐
相关产品推荐

