在 GraphQL 中查询关系数据(NoSQL 与 RDS)
Querying relational data in GraphQL (NoSQL v RDS)
我正在编写一个包含具有某些明显关系的整体数据模型的应用程序。我开始使用 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 },
},
})
}
所以这对我来说很有意义并且一直运行良好,我很好奇如果我切换到关系数据库是否会看到切实的 speed/performance 改进。例如,如果您在我的服务中看到的相同 .find
方法由 Postgres 而不是 MongoDB 支持,并且建立了适当的外键关系,则 可以我有理由期待速度提高? 我想我不会,因为它只是一个没有连接的简单获取。此外,虽然 submissionIds 是一个伪外键(因为 MongoDB),但它在这个设置中仍然充当一个。我想我不明白为什么 MongoDB 本质上是关系数据的错误选择,如果你可以使用 GraphQL 和 @ResolveField
之类的东西来获取你需要的任何东西。在这种情况下,由 GraphQL 支持的 RDS 的成功实施会是什么样子?
这是一个很好的问题,尽管我认为它会得到一些固执己见且不确定的答案。在与 SQL 和 NoSQL 数据库通信的多个生产 GraphQL 服务器上工作后,我的个人经验和建议是:
如果您要在 Postgres 等关系数据库上公开 GraphQL,并且您正在使用 NestJS 请不要手动编写 GraphQL 层
这 非常 耗时且容易出错,而且您将 运行 陷入与 N+1 和性能相关的各种问题,同时牺牲许多功能是通过首先使用 RDS 获得的(就像您正在谈论的连接)。作为曾经走过这条路的人,请不要
有大量非常强大的技术可以让您在 RDS 之上生成 GraphQL API。这些技术比解析 GraphQL AST 并将其转换为优化的单个 SQL 查询。我强烈建议您查看 Hasura and PostGraphile。这两者都会让您对自己的工作效率感到震惊。在 SQL 关系之上手动编写解析器只是浪费时间
然后可以将这些工具集成到您的 NestJS 应用程序中。如果您对 Hasura 特别感兴趣,我维护了可以帮助您的开源包 integrate it nicely with NestJS
我正在编写一个包含具有某些明显关系的整体数据模型的应用程序。我开始使用 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 },
},
})
}
所以这对我来说很有意义并且一直运行良好,我很好奇如果我切换到关系数据库是否会看到切实的 speed/performance 改进。例如,如果您在我的服务中看到的相同 .find
方法由 Postgres 而不是 MongoDB 支持,并且建立了适当的外键关系,则 可以我有理由期待速度提高? 我想我不会,因为它只是一个没有连接的简单获取。此外,虽然 submissionIds 是一个伪外键(因为 MongoDB),但它在这个设置中仍然充当一个。我想我不明白为什么 MongoDB 本质上是关系数据的错误选择,如果你可以使用 GraphQL 和 @ResolveField
之类的东西来获取你需要的任何东西。在这种情况下,由 GraphQL 支持的 RDS 的成功实施会是什么样子?
这是一个很好的问题,尽管我认为它会得到一些固执己见且不确定的答案。在与 SQL 和 NoSQL 数据库通信的多个生产 GraphQL 服务器上工作后,我的个人经验和建议是:
如果您要在 Postgres 等关系数据库上公开 GraphQL,并且您正在使用 NestJS 请不要手动编写 GraphQL 层
这 非常 耗时且容易出错,而且您将 运行 陷入与 N+1 和性能相关的各种问题,同时牺牲许多功能是通过首先使用 RDS 获得的(就像您正在谈论的连接)。作为曾经走过这条路的人,请不要
有大量非常强大的技术可以让您在 RDS 之上生成 GraphQL API。这些技术比解析 GraphQL AST 并将其转换为优化的单个 SQL 查询。我强烈建议您查看 Hasura and PostGraphile。这两者都会让您对自己的工作效率感到震惊。在 SQL 关系之上手动编写解析器只是浪费时间
然后可以将这些工具集成到您的 NestJS 应用程序中。如果您对 Hasura 特别感兴趣,我维护了可以帮助您的开源包 integrate it nicely with NestJS