首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何根据文档中的引用ID合并和观察Firestore中的两个集合?

如何根据文档中的引用ID合并和观察Firestore中的两个集合?
EN

Stack Overflow用户
提问于 2019-05-07 12:34:20
回答 1查看 831关注 0票数 1

我正在使用Google后端创建一个StencilJS应用程序(没有框架),我希望尽可能多地使用RxFireRxJS库来简化数据访问代码。如何将来自使用引用ID的两个不同集合的单个可观察流数据组合起来?

网上有几个我已经读过并尝试过的例子,每个例子都使用了不同程度的嵌套复杂度的操作符的不同组合。https://www.learnrxjs.io/似乎是一个很好的资源,但它没有提供对我来说有意义的业务实例。这个问题是非常相似的,也许唯一的区别是将其转换为使用RxFire?还在看那个。作为比较,在SQL中,这将是一个SELECT语句,引用ID上有一个INNER JOIN

具体来说,我有一个Games的集合

代码语言:javascript
复制
{ id: "abc000001", name: "Billiards" },
{ id: "abc000002", name: "Croquet" },
...

和一个Game Sessions的集合

代码语言:javascript
复制
{ id: "xyz000001", userId: "usr000001", gameId: "abc000001", duration: 30 },
{ id: "xyz000002", userId: "usr000001", gameId: "abc000001", duration: 45 },
{ id: "xyz000003", userId: "usr000001", gameId: "abc000002", duration: 55 },
...

我想观察一个合并的Game Sessions集合,其中gameId实际上是用Game.name替换的。

我目前有一个game-sessions-service.ts,它有一个函数来获取特定用户的会话:

代码语言:javascript
复制
import { collectionData } from 'rxfire/firestore';
import { Observable } from 'rxjs';
import { GameSession } from '../interfaces';

observeUserGameSesssions(userId: string): Observable<GameSession[]> {

    let collectionRef = this.db.collection('game-sessions');
    let query = collectionRef.where('userId', '==', userId);

    return collectionData(query, 'id);
}

我用pipemergeMap尝试过各种不同的东西,但我不明白如何使它们都能很好地结合在一起。我想建立一个接口GameSessionView来表示合并的数据:

代码语言:javascript
复制
export interface GameSessionView {
    id: string,
    userId: string,
    gameName: string,
    duration: number
}
代码语言:javascript
复制
observeUserGameSessionViews(userId: string): Observable<GameSessionView> {

    this.observeUserGameSessions(userId)
    .pipe(
        mergeMap(sessions => {
            // What do I do here? Iterate over sessions 
            // and embed other observables for each document?
        }
    )
}

可能,我只是停留在一个规范化的思维方式,所以我愿意接受更好的方法来管理数据的建议。我只是不想要太多的重复来保持同步。

EN

回答 1

Stack Overflow用户

发布于 2019-05-19 14:24:48

您可以使用以下代码(也可作为斯塔克布利茨):

代码语言:javascript
复制
const games: Game[] = [...];
const gameSessions: GameSession[] = [...];

combineLatest(
  of(games),
  of(gameSessions)
).pipe(
  switchMap(results => {
    const [gamesRes, gameSessionsRes] = results;
    const gameSessionViews: GameSessionView[] = gameSessionsRes.map(gameSession => ({
      id: gameSession.id,
      userId: gameSession.userId,
      gameName: gamesRes.find(game => game.id === gameSession.gameId).name,
      duration: gameSession.duration
    }));
    return of(gameSessionViews);
  })
).subscribe(mergedData => console.log(mergedData));

解释:

使用combineLatest,您可以组合来自多个Ober应收款的最新值。如果您有“多个(.)可观测到的,相互依赖的某种计算或确定”,可以使用它。

因此,假设GameGameSession的列表是可观察的,则可以组合每个列表的值。

switchMap中,通过迭代GameSession来创建GameSessionView类型的新对象,使用属性iduserIdduration,并在gameIdGame的第二个列表中找到gameName的值。请注意,本例中没有错误处理。

由于switchMap期望您返回另一个可观察到的列表,合并列表将与of(gameSessionViews)一起返回。

最后,您可以对此过程进行subscribe并查看预期的结果。

当然,这不是你唯一能做到的方法,但我觉得这是最简单的方法。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56022761

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档