Prisma嵌套查询take:1未生成SQL LIMIT,如何在数据库层面实现?
在Prisma中实现嵌套关联的数据库层面LIMIT过滤
要让Prisma在数据库层面为嵌套关联查询添加LIMIT(而非应用层事后过滤),可以通过子查询关联的方式实现,核心思路是先定位每个主表记录对应的目标关联记录ID,再通过ID筛选出单条记录。
具体实现代码
假设你的主表模型为Protocol,关联表AprRecords的外键为protocolId,且你通过createdAt字段排序取最新一条记录,调整后的findMany调用如下:
await prisma.protocol.findMany({ take: 50, skip: 0, include: { MainProtocol: true, Chain: true, Protocols: true, Tokens: true, // 处理 AprRecords:数据库层面仅取1条 AprRecords: { where: { id: { in: prisma.aprRecords.findMany({ select: { id: true }, where: { protocolId: prisma.protocol.id }, // 替换为你的外键字段 orderBy: { createdAt: 'desc' }, // 替换为你的排序规则 take: 1, }) } }, include: { /* 保留你原来的嵌套include内容 */ } }, // 同理处理 TvlRecords TvlRecords: { where: { id: { in: prisma.tvlRecords.findMany({ select: { id: true }, where: { protocolId: prisma.protocol.id }, orderBy: { createdAt: 'desc' }, take: 1, }) } }, include: { /* 保留你原来的嵌套include内容 */ } }, // 同理处理 DailyRewardsRecords DailyRewardsRecords: { where: { id: { in: prisma.dailyRewardsRecords.findMany({ select: { id: true }, where: { protocolId: prisma.protocol.id }, orderBy: { createdAt: 'desc' }, take: 1, }) } }, include: { /* 保留你原来的嵌套include内容 */ } } }, orderBy: { dailyRewards: "desc" }, })
原理说明
- 原写法中
include里的take是Prisma查询完所有关联记录后,在应用层截断结果,导致数据库返回大量冗余数据,性能损耗大。 - 子查询方式会先在数据库层面为每个主表记录筛选出目标关联记录的ID(仅1条),再通过ID精确查询对应记录,最终数据库只会返回需要的单条关联数据,避免了不必要的数据传输。
注意事项
- 替换代码中的模型名(如
protocol、aprRecords)、外键字段(如protocolId)和排序字段(如createdAt)为你实际的schema定义。 - 确保你的Prisma版本支持关联子查询(Prisma 2.16+已支持该特性)。
内容的提问来源于stack exchange,提问作者Alexandre Schaffner
相关产品推荐
相关产品推荐

