【问题标题】:How to query for a single doc with AngularFirestore?如何使用 AngularFirestore 查询单个文档?
【发布时间】:2020-03-19 04:24:42
【问题描述】:

如何构建仅限于单个文档的 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&lt;any&gt;; 而不是docs: Observable&lt;any[]&gt;;,所以我不必对结果使用*ngFor 循环?

我试过了

this.doc = db.collection('myCollection', ref => ref.where('name', '==', 'foobar').limit(1)).valueChanges();

【问题讨论】:

  • 添加了“import { take } from 'rxjs/operators';”但它没有给出查询中的 1 个文档 :(
  • stackoverflow.com/questions/46654670/… 请参阅此内容以供参考。你必须导入import { take } from 'rxjs/operators';
  • 你得到了什么?
  • 对象 "docs: Observable" 工作正常,但 "doc: Observable" 没有任何价值.. 甚至没有错误
  • 如果添加.subscribe(res =&gt; console.log('response', res)); 会怎样?

标签: angular typescript firebase angularfire2 angularfire


【解决方案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>

以前的解决方案

不要像某些 cmets 中建议的那样执行take(1):它完成了 observable,然后您将停止侦听更改(为什么要使用实时数据库呢?)。此外,您仍然会收到一系列结果...

如果你不知道文档的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,则映射到哪里。

【讨论】:

  • 当我这样做时,"{{ doc.name }}" 保持为空,并且 "{{ (doc | async)?.name }}" 给出错误 "Error: InvalidPipeArgument: '[对象对象]' 用于管道 'AsyncPipe'"。但是当我将这两个示例都放在 *.html 文件中时,“{{ doc.name }}”和“{{ (doc | async)?.name }}”、“{{ doc.name }}”会填充期望值。想法?
  • 你能在 stackblitz 上重现吗?使用 "{{ (doc | async)?.name }}" 应该是要走的路,因为 firebase 返回的 observable。您可以使用“{{doc | async | json}}”(或者如果您说这对您有用,则只需“{{doc | json}}”)并在我的地图中添加一个 console.log(val) 进行调试发布
  • 这是我的 StackBlitz,感谢您把它放在那里的想法。 stackblitz.com/edit/angular-lymeyp
  • 知道了!我在分叉时遇到了问题,但我成功了,我用相关代码更新了我的答案(我意识到我在之前的回复中的 if 中犯了一个错误?)
  • 我想你错过了水龙头导入。这是工作中的 stackblitz stackblitz.com/edit/angular-v7yff2
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-28
  • 2018-07-12
  • 1970-01-01
  • 2019-02-22
  • 2018-12-15
相关资源
最近更新 更多