簡體   English   中英

如何根據文檔中的參考ID合並並觀察Firestore中的兩個集合?

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

我正在使用Google Firestore后端創建一個StencilJS應用程序(無框架),並且我想盡可能多地使用RxFireRxJS庫來簡化數據訪問代碼。 如何將來自兩個使用引用ID的不同集合的數據合並到一個可觀察的流中?

我已經閱讀並嘗試了幾個在線示例,每個示例都使用不同級別的嵌套復雜性的運算符的不同組合。 https://www.learnrxjs.io/似乎是一個很好的資源,但是它沒有提供對我有意義的業務示例。 這個問題非常相似,也許唯一的區別是使用RxFire進行了一些翻譯嗎? 還在看着那個。 只是為了進行比較,在SQL中,這將是帶有引用ID的INNER JOINSELECT語句。

具體來說,我有一個Games集合:

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

以及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 },
...

我想觀察Game Sessions的合並集合,其中gameId本質上被Game.name取代。

我目前有一個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);
}

而且我嘗試使用pipemergeMap各種變體,但是我不知道如何使它們正確地組合在一起。 我想建立一個接口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?
        }
    )
}

可能地,我只是停留在規范化的思維方式上,因此我願意就更好的數據管理方式提出建議。 我只是不想過多的重復來保持同步。

您可以使用以下代碼(也可以作為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));

說明:
使用combineLatest您可以合並多個Obervable中的最新值。 如果您具有“彼此依賴進行某些計算或確定的多個(..)可觀測對象” ,則可以使用它。
因此,假設您的GameGameSession的列表都是Observables,則可以合並每個列表的值。
switchMap創建類型的新對象GameSessionView通過遍歷您GameSession S,使用的屬性iduserIdduration ,並找到價值gameName的第二列表中Game由s gameId 請注意,此示例中沒有錯誤處理。
正如switchMap期望您返回另一個Observable一樣,合並列表將與of(gameSessionViews)返回。
最后,您可以subscribe此過程並查看預期結果。

當然,這不是唯一的方法,但我發現它是最簡單的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM