我正在编写一个应用程序,其中包含一个具有一些明显关系的整体数据模型。我开始使用MongoDB编写应用程序,但决定尝试过渡到Postgres,因为我的数据有大量的"外键"。为简单起见,让我们考虑以下模型:
class GameBase {
id: string
entryIds: string[]
submissionIds: string[]
}
class EntryBase {
id: string
description: string
gameId: string
userId: string // id of user who supplied entry
submissionIds: string[] // submissions where entry is covered
}
class SubmissionBase {
id: string
url: string
gameId: string
userId: string // id of user who submitted
entryIds: string[] // entries covered by submission
}
现在我明白了,如果我使用像TypeOrm这样的工具,我可以通过如下方式检索这些关系:
const games = await gameRepository.find({ relations: ["entryIds", "submissionIds"] });
但我不太确定这与 GraphQL 有什么关系。到目前为止,我一直在做的是在我的解析器中添加@ResolveField
并编写类似的东西
// game.resolver.ts
@ResolveField(() => [SubmissionBase], { nullable: true })
submissions(@Parent() game: GameBase) {
return this.submissionService.getManySubmissions(game.submissionIds)
}
并在服务中
// game.service.ts
async getManySubmissions(submissionIds: string[]): Promise<SubmissionBase[]> {
if (!submissionIds) return []
return await this.submissionRepository.find({
where: {
id: { $in: submissionIds },
},
})
}
所以这对我来说很有意义并且一直工作得很好,我只是好奇如果我切换到关系数据库,我是否会看到明显的速度/性能改进。例如,如果您在我的服务中看到的相同.find
方法由 Postgres 而不是 MongoDB 支持,并且建立了适当的外键关系,我是否可以合理地期望速度提高?我想我不会,因为它只是一个没有连接的简单获取。此外,尽管 submitIds 是一个伪外键(因为 MongoDB(,但它在此设置中仍然充当一个。我想我没有明白为什么MongoDB本质上是关系数据的错误选择,如果你可以使用GraphQL和类似@ResolveField
的东西来获取你需要的任何东西。在这种情况下,由 GraphQL 支持的 RDS 的成功实现会是什么样子?
这是一个很好的问题,尽管我认为它会得到一些固执己见和非确定的答案。在多个生产 GraphQL 服务器上与 SQL 和 NoSQL 数据库通信后,我的个人经验和建议是这样的:
如果你打算通过像Postgres这样的关系数据库公开GraphQL,并且你正在使用NestJS,请不要手动编写GraphQL层。
它非常耗时且容易出错,而且您会遇到与 N+1 和性能相关的各种问题,同时牺牲了首先使用 RDS 获得的许多功能(例如您正在谈论的联接(。作为一个以前走过这条路的人,请不要
有大量非常强大的技术允许您在 RDS 之上生成 GraphQL API。这些技术解析 GraphQL AST 并将其转换为优化的单个 SQL 查询。我强烈建议你看看Hasura和PostGraphile。这两者都会让你对你的工作效率感到震惊。在 SQL 关系之上手动编写解析器只是浪费时间
然后,这些工具可以集成到您的NestJS应用程序中。如果你对Hasura特别感兴趣,我维护开源包,可以帮助你与NestJS很好地集成它
。