从 Firestore 中检索文档引用的值
Posted
技术标签:
【中文标题】从 Firestore 中检索文档引用的值【英文标题】:Retrieving value of document references from firestore 【发布时间】:2021-05-06 08:24:45 【问题描述】:我正在尝试从 firestore(一个问题对象)中检索一个对象,该对象除其他外具有一些 DocumentReference 类型的字段(例如:主题,指的是主题集合中的一个文档)。这里的目标是从问题集合中检索所有问题对象,在表格中显示它们的所有属性,并且应该解析 DocumentReferences,并且应该显示检索到的对象的“名称”属性。解决所有问题很容易,但出于某种原因,我为解决 DocumentReferences 所做的工作导致整个应用程序冻结
themes.service.ts
getThemeNameByRef(ref: DocumentReference): Observable<string>
if (ref)
return this.db.doc(`themes/$ref.id`).get()
.pipe(
map((action) =>
return action.data().name;
), shareReplay(1))
问题-explorer.component.html
<div *ngFor="let question of questions">
question.difficulty
themeService.getThemeNameByRef(question.theme) | async
</div>
我已将其包含在表格中,并使用更简单的方法来消除导致问题的原因。我已经尝试了很多不同的方法来检索引用,比如直接在 DocumentReference 对象上调用 get(),创建一个 AngularFirestoreDocument 对象,我似乎遇到了同样的冻结问题,或者页面会加载但模板会解析值为 null,因此不会显示任何内容。
查看 Chrome 开发工具,只有一个 HTTP 请求发出,但 observable 被无限次调用,这就是导致它冻结的副作用。为什么会这样,但我无法弄清楚。
谢谢!
【问题讨论】:
【参考方案1】:部分解决方案:
我不确定你发生了什么,我希望问题数组中的每个问题都有一个 HTTP 调用。
无论如何,从长远来看,直接在 HTML 模板中编写数据可能是一个糟糕的选择。如果您的服务调用的结果无序或以不同的时间间隔返回,则很难扩展,并且可能会导致视图显示异常。
在您的组件中,我会写如下内容:
(请注意,我不确定questions
是如何定义的,所以我无法建议应该在哪里/如何声明/定义viewQuestions$
,这取决于您)
viewQuestions$ = forkJoin(
this.questions.map(question =>
themeService.getThemeNameByRef(question.theme).pipe(
map(theme => (...question, theme))
)
)
);
然后在你的 HTML 模板中
<div *ngFor="let question of viewQuestions$ | async">
question.difficulty
question.theme
</div>
这有一个更简单的模板的好处。所有的服务调用都在显示之前完成,所以用户屏幕上没有奇怪的闪烁。
您也可以更轻松地调试它。您可以使用 RxJS 运算符来记录结果、捕获错误、重试服务调用等。
例如,如果您想在问题显示之前记录问题,您可以执行以下操作:
viewQuestions$ = forkJoin(
this.questions.map(question =>
themeService.getThemeNameByRef(question.theme).pipe(
map(theme => (...quesiton, theme))
)
)
).pipe(
tap(console.log)
);
进一步抽象构建viewQuestions$
这与上述相同,但适用于任意数量的属性。 forkjoin
的好处是它接受一个字典(JS 对象),并将返回一个形状相同的对象,其属性解析为给定 observables 的最终值。很方便!
你可以看到这里使用的:
viewQuestions$ = this.getQuestionsService(args).pipe(
switchMap(questions => forkJoin(
questions.map(question =>
forkJoin(
theme: this.themeService.getThemeNameByRef(question.theme),
property2: this.service.getThingy2(question.something2),
property3: this.service.getThingy3(question.something3)
).pipe(
map(properties => (...question, ...properties))
)
)
))
);
在您的模板中:
<div *ngFor="let question of viewQuestions$ | async">
question.difficulty
question.theme
question.property2
question.property3
</div>
【讨论】:
这真的很漂亮,我理想的解决方案是一次性解决所有问题,这就是您在这里所做的。这将作为构建我的表格的一个很好的起点,因为它可以正确解析文档。感谢您的帮助,请继续做您的事情! 一个问题有多少个 DocumentReference? 目前是 5,我看到你在那里做的很干净。我今晚会实施。谢谢!!以上是关于从 Firestore 中检索文档引用的值的主要内容,如果未能解决你的问题,请参考以下文章
从 documentSnapshot 获取 Cloud Firestore 文档参考
如何从Swift中的Cloud FireStore Firebase访问特定字段