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

Pothos搭配Prisma是否支持Group By?如何实现分组查询

问题描述

现有代码:

export const StockDelivery = builder.prismaObject("StockDelivery", {
  fields: (t) => ({
    id: t.exposeID("id", { nullable: false }),
    createdAt: t.expose("createdAt", { type: "DateScalar", nullable: false }),
    modifiedAt: t.expose("modifiedAt", { type: "DateScalar", nullable: false }),
    expectedAt: t.expose("expectedAt", { type: "DateScalar", nullable: false }),
    deliveredAt: t.expose("deliveredAt", { type: "DateScalar", nullable: true }),
    supplier: t.relation("supplier", { nullable: false }),
    commodity: t.relation("commodity", { nullable: false }),

    cost: t.exposeFloat("cost", { nullable: false }),
    qty: t.exposeInt("qty", { nullable: false }),
    cancelled: t.exposeBoolean("cancelled", { nullable: false }),
  }),
});

想要创建名为shipments的查询,将StockDelivery按expectedAt日期和供应商(supplier)分组。已知Prisma有prisma.stockDelivery.groupBy({...})方法,但不清楚如何和Pothos结合,猜测需要创建StockDelivery prismaObject的自定义变体,但Pothos文档没提分组相关内容,求可行解决方案。

解决方案

Pothos本身没有直接封装Prisma的groupBy能力,但可以通过自定义对象类型+手动编写Resolver的方式实现,步骤如下:

1. 创建分组结果的自定义对象类型

先定义一个新的对象类型,用来承载分组后的数据结构,包含分组键(日期、供应商)以及你需要的聚合字段:

// 定义分组结果类型
export const StockDeliveryGroup = builder.objectType("StockDeliveryGroup", {
  fields: (t) => ({
    expectedAt: t.field({ type: "DateScalar", nullable: false }),
    supplier: t.field({ type: Supplier, nullable: false }), // 假设你已定义Supplier类型
    totalQty: t.int({ nullable: false }),
    totalCost: t.float({ nullable: false }),
    count: t.int({ nullable: false }), // 分组内的记录总数
  }),
});

2. 添加shipments查询字段

在查询类型中添加shipments字段,返回上面定义的分组结果列表:

builder.queryField("shipments", (t) =>
  t.field({
    type: [StockDeliveryGroup],
    args: {
      // 按需添加过滤参数,比如日期范围
      startDate: t.arg({ type: "DateScalar", nullable: true }),
      endDate: t.arg({ type: "DateScalar", nullable: true }),
    },
    resolve: async (_, args, { prisma }) => {
      // 调用Prisma的groupBy方法,注意分组键要用外键ID
      const groups = await prisma.stockDelivery.groupBy({
        by: ["expectedAt", "supplierId"],
        where: {
          // 按需添加过滤条件
          ...(args.startDate && { expectedAt: { gte: args.startDate } }),
          ...(args.endDate && { expectedAt: { lte: args.endDate } }),
          cancelled: false, // 排除已取消的记录
        },
        _sum: {
          qty: true,
          cost: true,
        },
        _count: {
          id: true,
        },
        orderBy: {
          expectedAt: "asc",
        },
      });

      // 手动查询供应商信息,因为groupBy仅返回supplierId
      const supplierIds = groups.map((g) => g.supplierId);
      const suppliers = await prisma.supplier.findMany({
        where: { id: { in: supplierIds } },
      });
      const supplierMap = new Map(suppliers.map((s) => [s.id, s]));

      // 转换为自定义分组类型的结构
      return groups.map((group) => ({
        expectedAt: group.expectedAt,
        supplier: supplierMap.get(group.supplierId)!,
        totalQty: group._sum.qty!,
        totalCost: group._sum.cost!,
        count: group._count.id!,
      }));
    },
  })
);

关键说明

  • Prisma的groupBy只能直接返回分组键(如supplierId)和聚合结果,无法直接关联返回supplier对象,因此需要手动查询供应商并做映射。
  • 自定义对象类型可根据需求调整字段,比如只保留分组键,或者添加_avg、_max等其他聚合值。
  • 如果不需要聚合字段,仅需分组后的基础数据,可在groupBy后通过分组键批量查询对应记录。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 11:05:04