Skip to content
VibORM
Esc
navigateopen⌘Jpreview
On this page

groupBy

Group records and compute aggregates per group

Group records by one or more fields and compute aggregates per group:

const byRole = await client.user.groupBy({
  by: ["role"],
  _count: true,
});

// Result:
// [
//   { role: "USER", _count: 100 },
//   { role: "ADMIN", _count: 5 },
// ]

With aggregates

const stats = await client.post.groupBy({
  by: ["authorId"],
  _count: true,
  _avg: { views: true },
  _sum: { views: true },
});

// [
//   { authorId: "user_1", _count: 10, _avg: { views: 50 }, _sum: { views: 500 } },
//   { authorId: "user_2", _count: 5, _avg: { views: 100 }, _sum: { views: 500 } },
// ]

With filtering

Use where to filter rows before grouping, and having to filter groups after:

const stats = await client.post.groupBy({
  by: ["authorId"],
  where: { published: true },
  _count: true,
  having: {
    authorId: { _count: { gt: 5 } }, // Only authors with 5+ posts
  },
  orderBy: { _count: { _all: "desc" } },
  take: 10,
});

Options

await client.post.groupBy({
  by: ["field1", "field2"],  // Group by fields
  where: { ... },            // Filter before grouping
  having: { ... },           // Filter after grouping
  orderBy: { ... },          // Sort groups
  take: 10,                  // Limit groups
  skip: 0,                   // Offset groups
  _count: true | { ... },
  _avg: { ... },
  _sum: { ... },
  _min: { ... },
  _max: { ... },
});

Examples

Top authors

async function getTopAuthors(limit = 10) {
  return client.post.groupBy({
    by: ["authorId"],
    where: { published: true },
    _count: true,
    _sum: { views: true },
    orderBy: { _sum: { views: "desc" } },
    take: limit,
  });
}

Was this page helpful?