跳至内容

聚合、分组和汇总

Prisma Dart 客户端允许您计算记录数、聚合数字字段以及选择不同的字段值。

聚合

Prisma Dart 客户端允许您对模型的**数字**字段(例如IntFloat)进行aggregate操作。以下查询返回所有用户的平均年龄

dart
final aggregate1 = await prisma.user.aggregate(
  select: AggregateUserSelect(
    $avg: PrismaUnion.$2(
      AggregateUserAvgArgs(
        select: UserAvgAggregateOutputTypeSelect(age: true),
      ),
    ),
  ),
);
print("Average age: ${aggregate1.$avg?.age}");

您可以将聚合与过滤和排序结合使用。例如,以下查询返回用户的平均年龄

  • age升序排序
  • 其中email包含hello
  • 限制为前10个用户
dart
final aggregate2 = await prisma.user.aggregate(
  select: AggregateUserSelect(
    $avg: PrismaUnion.$2(
      AggregateUserAvgArgs(
        select: UserAvgAggregateOutputTypeSelect(age: true),
      ),
    ),
  ),
  where: UserWhereInput(
    email: PrismaUnion.$1(
      StringFilter(contains: PrismaUnion.$1('hello')),
    ),
  ),
  take: 10,
);
print("Average age: ${aggregate2.$avg?.age}");

聚合值可以为 null

对**可空字段**的聚合可以返回numnull。这排除了$count,如果未找到任何记录,它始终返回0。

考虑以下查询,其中age在模式中是可空的

dart
await prisma.user.aggregate(
  select: AggregateUserSelect(
    $avg: PrismaUnion.$2(
      AggregateUserAvgArgs(
        select: UserAvgAggregateOutputTypeSelect(age: true),
      ),
    ),
    $count: PrismaUnion.$2(
      AggregateUserCountArgs(
        select: UserCountAggregateOutputTypeSelect(age: true),
      ),
    ),
  ),
);

在以下任何一种情况下,查询都会返回{ _avg: { age: null } }

  • 没有用户
  • 每个用户的age字段的值均为null

这使您能够区分真正的聚合值(可能是零)和无数据。

分组依据

Prisma Datr 客户端groupBy允许您按一个或多个字段值(例如countrycountrycity)**对记录进行分组**,并在每个组中**执行聚合**操作,例如查找居住在特定城市的人的平均年龄。

以下示例按country字段对所有用户进行分组,并返回每个国家/地区的个人资料查看总数

dart
await prisma.user.groupBy(
  by: PrismaUnion.$1([
    UserScalar.country,
  ]),
  select: UserGroupByOutputTypeSelect(
    country: true,
    $sum: PrismaUnion.$2(
      UserGroupByOutputTypeSumArgs(
        select: UserSumAggregateOutputTypeSelect(
          profileViews: true,
        ),
      ),
    ),
  ),
);

如果您在by选项中只有一个元素,则可以使用以下简写语法来表达您的查询

dart
await prisma.user.groupBy(
  by: PrismaUnion.$2(UserScalar.country),
);

groupBy和过滤

groupBy支持两个级别的过滤:wherehaving

使用where过滤记录

使用where在**分组前**过滤所有记录。以下示例按国家/地区对用户进行分组并对个人资料查看次数求和,但仅包括电子邮件地址包含test的用户

dart
await prisma.user.groupBy(
  by: PrismaUnion.$1([
    UserScalar.country,
  ]),
  select: UserGroupByOutputTypeSelect(
    country: true,
    $sum: PrismaUnion.$2(
      UserGroupByOutputTypeSumArgs(
        select: UserSumAggregateOutputTypeSelect(
          profileViews: true,
        ),
      ),
    ),
  ),

  where: UserWhereInput(
    email: PrismaUnion.$1(
      StringFilter(contains: PrismaUnion.$1('test')),
    ),
  ),
);

使用having过滤组

使用having按聚合值(例如字段的总和或平均值)过滤整个组,而不是单个记录——例如,仅返回平均profileViews大于100的组

dart
await prisma.user.groupBy(
  by: PrismaUnion.$1([
    UserScalar.country,
  ]),
  select: UserGroupByOutputTypeSelect(
    country: true,
    $sum: PrismaUnion.$2(
      UserGroupByOutputTypeSumArgs(
        select: UserSumAggregateOutputTypeSelect(
          profileViews: true,
        ),
      ),
    ),
  ),

  having: UserScalarWhereWithAggregatesInput(
    profileViews: PrismaUnion.$1(
      IntWithAggregatesFilter(
        $avg: NestedFloatFilter(
          gt: PrismaUnion.$1(100),
        ),
      ),
    ),
  ),
);

groupBy和排序

当您将groupByorderBy结合使用时,适用以下约束条件

  • 您可以对by中存在的字段进行orderBy
  • 您可以对聚合进行orderBy
  • 如果您将skip和/或takegroupBy一起使用,则必须在查询中也包含orderBy

按聚合组排序

以下示例按每个city组中的用户数量对每个city组进行排序(最大的组排在最前面)

dart
await prisma.user.groupBy(
  by: PrismaUnion.$1([UserScalar.city]),
  select: UserGroupByOutputTypeSelect(
    city: true,
    $count: PrismaUnion.$2(
      UserGroupByOutputTypeCountArgs(
        select: UserCountAggregateOutputTypeSelect(
          city: true,
        ),
      ),
    ),
  ),
  orderBy: PrismaUnion.$2(
    UserOrderByWithAggregationInput(
      $count: UserCountOrderByAggregateInput(
        city: SortOrder.desc,
      ),
    ),
  ),
);

按字段排序

以下查询按国家/地区对组进行排序,跳过前两个组,并返回第3个和第4个组

dart
await prisma.user.groupBy(
  by: PrismaUnion.$1([UserScalar.country]),
  select: UserGroupByOutputTypeSelect(
    country: true,
    $sum: PrismaUnion.$2(
      UserGroupByOutputTypeSumArgs(
        select: UserSumAggregateOutputTypeSelect(
          profileViews: true,
        ),
      ),
    ),
  ),
  orderBy: PrismaUnion.$2(
    UserOrderByWithAggregationInput(
      $count: UserCountOrderByAggregateInput(
        country: SortOrder.desc,
      ),
    ),
  ),
  take: 2,
  skip: 2,
);

在 BSD-3-Clause 许可证下发布