![](/img/trans.png)
[英]How to use cloud function trigger based on two collections documents
[英]How to merge and observe two collections in Firestore based on reference ID in documents?
我正在使用Google Firestore后端創建一個StencilJS
應用程序(無框架),並且我想盡可能多地使用RxFire
和RxJS
庫來簡化數據訪問代碼。 如何將來自兩個使用引用ID的不同集合的數據合並到一個可觀察的流中?
我已經閱讀並嘗試了幾個在線示例,每個示例都使用不同級別的嵌套復雜性的運算符的不同組合。 https://www.learnrxjs.io/似乎是一個很好的資源,但是它沒有提供對我有意義的業務示例。 這個問題非常相似,也許唯一的區別是使用RxFire進行了一些翻譯嗎? 還在看着那個。 只是為了進行比較,在SQL中,這將是帶有引用ID的INNER JOIN
的SELECT
語句。
具體來說,我有一個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);
}
而且我嘗試使用pipe
和mergeMap
各種變體,但是我不知道如何使它們正確地組合在一起。 我想建立一個接口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中的最新值。 如果您具有“彼此依賴進行某些計算或確定的多個(..)可觀測對象” ,則可以使用它。
因此,假設您的Game
和GameSession
的列表都是Observables,則可以合並每個列表的值。
內switchMap
創建類型的新對象GameSessionView
通過遍歷您GameSession
S,使用的屬性id
, userId
和duration
,並找到價值gameName
的第二列表中Game
由s gameId
。 請注意,此示例中沒有錯誤處理。
正如switchMap
期望您返回另一個Observable一樣,合並列表將與of(gameSessionViews)
返回。
最后,您可以subscribe
此過程並查看預期結果。
當然,這不是唯一的方法,但我發現它是最簡單的方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.