You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Prisma中单次请求完成findMany与count查询并保留类型?

解决方案

1. 解决重复条件+类型丢失问题(推荐方案)

直接复用Prisma自动生成的CategoryWhereInput类型定义筛选条件,既能避免重复编写where逻辑,又能保留完整的TypeScript类型提示,同时通过Promise.all并行执行查询,减少总耗时:

async findAll(
  { onlyParents }: ParamsCategoryDto,
  user: ITokenPayload | undefined,
): Promise<IFilterRes> {
  // 用Prisma生成的类型定义筛选条件,自动保留类型提示
  const where: Prisma.CategoryWhereInput = {
    user_id: user?.id,
    // 按需添加其他筛选逻辑,比如onlyParents的判断
    ...(onlyParents ? { parent_id: null } : {}),
  };

  // 并行执行查询,复用数据库连接池,效率比串行更高
  const [categories, total] = await Promise.all([
    this.prisma.category.findMany({ where }),
    this.prisma.category.count({ where }),
  ]);

  return {
    pagination: { total },
    data: categories,
  };
}

2. 单数据库查询实现(极致性能场景)

如果需要严格意义上的一次数据库请求完成数据和总数查询,可以用Prisma的原生SQL查询能力,但需要手动处理类型映射,适合对性能有极致要求的场景:

async findAll(
  { onlyParents }: ParamsCategoryDto,
  user: ITokenPayload | undefined,
): Promise<IFilterRes> {
  const userId = user?.id;
  // 动态拼接筛选条件,注意用Prisma的raw方法避免SQL注入
  const extraCondition = onlyParents 
    ? prisma.raw('AND parent_id IS NULL') 
    : prisma.raw('');

  // 原生SQL同时查询总数和数据
  const queryResult = await this.prisma.$queryRaw`
    SELECT 
      (SELECT COUNT(*) FROM category WHERE user_id = ${userId} ${extraCondition}) AS total,
      json_agg(row_to_json(c)) AS data
    FROM category c
    WHERE c.user_id = ${userId} ${extraCondition}
  `;

  // 手动断言类型,匹配你的返回结构
  const { total, data } = queryResult[0] as { total: number; data: Category[] };
  return {
    pagination: { total },
    data,
  };
}

说明

  • 推荐第一种方案:代码简洁、类型安全、并行查询的性能损耗可以忽略,是Prisma实现分页的常规做法
  • 第二种方案仅在需要极致性能时考虑,需要注意SQL注入风险(Prisma的参数化查询会帮你处理大部分风险,但动态拼接条件时要谨慎)

内容的提问来源于stack exchange,提问作者SPR1NG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 13:35:41