我如何构建仅限于单个文档的Observable?
这在查询任意数量的文档时会建立一个Observable:
foo.component.ts
import { AngularFirestore } from '@angular/fire/firestore';
import { Observable } from 'rxjs';
...
export class FooComponent implements OnInit {
...
docs: Observable<any[]>;
constructor(private db: AngularFirestore) {
this.docs = db.collection('myCollection', ref => ref.where('name', '==', 'foobar')).valueChanges();
}
foo.component.html
<div *ngFor="let doc of docs | async">
{{ doc.name }}, {{ doc.address }}
</div>
当我知道将只返回1个文档时,该怎么办?我只是事先不知道文档ID。
类似于上面的代码,只是用doc: Observable<any>;
而不是docs: Observable<any[]>;
,所以我不必对结果使用*ngFor
循环吗?
我尝试过
this.doc = db.collection('myCollection', ref => ref.where('name', '==', 'foobar').limit(1)).valueChanges();
答案 0 :(得分:1)
有效的堆叠闪电战:https://stackblitz.com/edit/angular-v7yff2
基于https://stackblitz.com/edit/angular-lymeyp,您只需要在组件中执行以下操作
crazinessToObserveASingleDoc() {
this.singleDoc = this.db.collection('users', ref => ref.where('email', '==', this.email)).valueChanges().pipe(
tap(docs => console.log('docs', docs)),
map(val => val.length > 0 ? val[0] : null)
)
}
和模板中
<div>
<span class="title">Document with email <span class="italics">{{ email }}</span>:</span>
<div *ngIf="singleDoc | async as doc">{{ doc.name }}, {{ doc.email }}</div>
</div>
以前的解决方案
不要像某些注释中建议的那样take(1)
:完成可观察的操作,然后您将停止侦听更改(为什么要使用实时数据库?)。此外,您仍然会收到一系列结果...
如果您不知道文档的ID,则需要执行以下操作:
const doc: Observable<any | null> =
db.collection('myCollection', ref => ref.where('name', '==', 'foobar'))
.valueChanges()
.pipe(map(val => val.length > 0 : val[0] : null));
如果来自rxjs/operators
的位置图。