简体   繁体   English

如何根据文档中的参考ID合并并观察Firestore中的两个集合?

[英]How to merge and observe two collections in Firestore based on reference ID in documents?

I'm creating a StencilJS app (no framework) with a Google Firestore backend, and I want to use the RxFire and RxJS libraries as much as possible to simplify data access code. 我正在使用Google Firestore后端创建一个StencilJS应用程序(无框架),并且我想尽可能多地使用RxFireRxJS库来简化数据访问代码。 How can I combine into a single observable stream data coming from two different collections that use a reference ID? 如何将来自两个使用引用ID的不同集合的数据合并到一个可观察的流中?

There are several examples online that I've read through and tried, each one using a different combination of operators with a different level of nested complexity. 我已经阅读并尝试了几个在线示例,每个示例都使用不同级别的嵌套复杂性的运算符的不同组合。 https://www.learnrxjs.io/ seems like a good resource, but it does not provide line-of-business examples that make sense to me. https://www.learnrxjs.io/似乎是一个很好的资源,但是它没有提供对我有意义的业务示例。 This question is very similar, and maybe the only difference is some translation into using RxFire? 这个问题非常相似,也许唯一的区别是使用RxFire进行了一些翻译吗? Still looking at that. 还在看着那个。 Just for comparison, in SQL this would be a SELECT statement with an INNER JOIN on the reference ID. 只是为了进行比较,在SQL中,这将是带有引用ID的INNER JOINSELECT语句。

Specifically, I have a collection for Games : 具体来说,我有一个Games集合:

{ id: "abc000001", name: "Billiards" },
{ id: "abc000002", name: "Croquet" },
...

and a collection for Game Sessions : 以及Game Sessions的集合:

{ id: "xyz000001", userId: "usr000001", gameId: "abc000001", duration: 30 },
{ id: "xyz000002", userId: "usr000001", gameId: "abc000001", duration: 45 },
{ id: "xyz000003", userId: "usr000001", gameId: "abc000002", duration: 55 },
...

And I want to observe a merged collection of Game Sessions where gameId is essentially replace with Game.name . 我想观察Game Sessions的合并集合,其中gameId本质上被Game.name取代。

I current have a game-sessions-service.ts with a function to get sessions for a particular user: 我目前有一个game-sessions-service.ts ,它具有为特定用户获取会话的功能:

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);
}

And I've tried variations of things with pipe and mergeMap , but I don't understand how to make them all fit together properly. 而且我尝试使用pipemergeMap各种变体,但是我不知道如何使它们正确地组合在一起。 I would like to establish an interface GameSessionView to represent the merged data: 我想建立一个接口GameSessionView来代表合并后的数据:

export interface GameSessionView {
    id: string,
    userId: string,
    gameName: string,
    duration: number
}

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?
        }
    )
}

Possibly, I'm just stuck in a normalized way of thinking, so I'm open to suggestions on better ways to manage the data. 可能地,我只是停留在规范化的思维方式上,因此我愿意就更好的数据管理方式提出建议。 I just don't want too much duplication to keep synchronized. 我只是不想过多的重复来保持同步。

You can use the following code (also available as Stackblitz ): 您可以使用以下代码(也可以作为Stackblitz使用 ):

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));

Explanation: 说明:
With combineLatest you can combine the latest values from a number of Obervables. 使用combineLatest您可以合并多个Obervable中的最新值。 It can be used if you have "multiple (..) observables that rely on eachother for some calculation or determination" . 如果您具有“彼此依赖进行某些计算或确定的多个(..)可观测对象” ,则可以使用它。
So assuming you lists of Game s and GameSession s are Observables, you can combine the values of each list. 因此,假设您的GameGameSession的列表都是Observables,则可以合并每个列表的值。
Within the switchMap you create new objects of type GameSessionView by iterating over your GameSession s, use the attributes id , userId and duration and find the value for gameName within the second list of Game s by gameId . switchMap创建类型的新对象GameSessionView通过遍历您GameSession S,使用的属性iduserIdduration ,并找到价值gameName的第二列表中Game由s gameId Mind that there is no error handling in this example. 请注意,此示例中没有错误处理。
As switchMap expects that you return another Observable, the merged list will be returned with of(gameSessionViews) . 正如switchMap期望您返回另一个Observable一样,合并列表将与of(gameSessionViews)返回。
Finally, you can subscribe to this process and see the expected result. 最后,您可以subscribe此过程并查看预期结果。

For sure this is not the only way you can do it, but I find it the simplest one. 当然,这不是唯一的方法,但我发现它是最简单的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用基于两个collections文件的云function触发器 - How to use cloud function trigger based on two collections documents 如何使用UnderscoreJS通过&#39;id&#39;联合/合并两个集合 - How do I union/merge two Collections by their 'id' using UnderscoreJS 如何使用 Lodash 基于一个键合并两个集合? - How to use Lodash to merge two collections based on a key? 如何根据id合并这两个arrays? - How to merge these two arrays based on the id? 如何从 Firestore 两个 collections 获取数据并将所有数据合并在一起 - how can get data from firestore two collections and merge all data together "Firestore 更新集合中的所有文档" - Firestore update all documents in collections 如何在Cloud Firestore(Web)中获取所有不带名称的集合和文档 - How to get all collections and documents without their names in Cloud Firestore (web) Firestore:如何遍历一些文档并获取子 collections? - Firestore: How to iterate through some documents and get the sub collections? 如何获取所有 Firestore Collections 和文档? | 反应JS - How to Get all Firestore Collections and Documents? | React JS 根据firestore中的引用路径获取子集合的文档 - Get documents of subcollections based on reference path from firestore
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM