我正在使用Google后端创建一个StencilJS应用程序(没有框架),我希望尽可能多地使用RxFire和RxJS库来简化数据访问代码。如何将来自使用引用ID的两个不同集合的单个可观察流数据组合起来?
网上有几个我已经读过并尝试过的例子,每个例子都使用了不同程度的嵌套复杂度的操作符的不同组合。https://www.learnrxjs.io/似乎是一个很好的资源,但它没有提供对我来说有意义的业务实例。这个问题是非常相似的,也许唯一的区别是将其转换为使用RxFire?还在看那个。作为比较,在SQL中,这将是一个SELECT语句,引用ID上有一个INNER JOIN。
具体来说,我有一个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?
}
)
}可能,我只是停留在一个规范化的思维方式,所以我愿意接受更好的方法来管理数据的建议。我只是不想要太多的重复来保持同步。
发布于 2019-05-19 14:24:48
您可以使用以下代码(也可作为斯塔克布利茨):
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应收款的最新值。如果您有“多个(.)可观测到的,相互依赖的某种计算或确定”,可以使用它。
因此,假设Game和GameSession的列表是可观察的,则可以组合每个列表的值。
在switchMap中,通过迭代GameSession来创建GameSessionView类型的新对象,使用属性id、userId和duration,并在gameId的Game的第二个列表中找到gameName的值。请注意,本例中没有错误处理。
由于switchMap期望您返回另一个可观察到的列表,合并列表将与of(gameSessionViews)一起返回。
最后,您可以对此过程进行subscribe并查看预期的结果。
当然,这不是你唯一能做到的方法,但我觉得这是最简单的方法。
https://stackoverflow.com/questions/56022761
复制相似问题