Aggregations
Learn how to perform calculations on your data using Ductape's aggregation API. This guide covers counting, summing, averaging, grouping, and multi-aggregation operations.
Quick Example
- TypeScript
- Java
- Go
- .NET
const stats = await ductape.database.aggregate({
table: 'orders',
operations: {
total_orders: { $count: '*' },
total_revenue: { $sum: 'total' },
avg_order_value: { $avg: 'total' },
min_order: { $min: 'total' },
max_order: { $max: 'total' },
},
where: { status: 'completed' },
});
console.log('Total Orders:', stats.total_orders);
console.log('Total Revenue:', stats.total_revenue);
console.log('Average Order:', stats.avg_order_value);
Map<String, Object> stats = ductape.database.aggregate(Map.of(
"table", "orders",
operations: Map.of(
total_orders: Map.of( $"count", "*" ),
total_revenue: Map.of( $"sum", "total" ),
avg_order_value: Map.of( $"avg", "total" ),
min_order: Map.of( $"min", "total" ),
max_order: Map.of( $"max", "total" )
),
where: Map.of( "status", "completed" )
));
System.out.println('Total "Orders", ", stats.total_orders);
System.out.println("Total "Revenue", ", stats.total_revenue);
System.out.println("Average Order:', stats.avg_order_value);
stats := client.database.aggregate({
"table": "orders",
operations: {
total_orders: { $"count": "*" },
total_revenue: { $"sum": "total" },
avg_order_value: { $"avg": "total" },
min_order: { $"min": "total" },
max_order: { $"max": "total" },
},
where: { "status": "completed" },
});
fmt.Println('Total "Orders": ", stats.total_orders);
fmt.Println("Total "Revenue": ", stats.total_revenue);
fmt.Println("Average Order:', stats.avg_order_value);
var stats = await ductape.database.aggregate({
["table"] = "orders",
operations: {
total_orders: { $["count"] = "*" },
total_revenue: { $["sum"] = "total" },
avg_order_value: { $["avg"] = "total" },
min_order: { $["min"] = "total" },
max_order: { $["max"] = "total" },
},
where: { ["status"] = "completed" },
});
Console.WriteLine('Total ["Orders"] = ", stats.total_orders);
Console.WriteLine("Total ["Revenue"] = ", stats.total_revenue);
Console.WriteLine("Average Order:', stats.avg_order_value);
Aggregation Syntax
Ductape uses a clean, object-based syntax for aggregations with lowercase operators following the Mongoose/MongoDB convention:
- TypeScript
- Java
- Go
- .NET
{
alias_name: { $function: 'column_name' }
}
Map.of(
alias_name: Map.of( $"function", "column_name" )
)
{
alias_name: { $"function": "column_name" }
}
{
alias_name: { $["function"] = "column_name" }
}
Supported Functions
| Function | Description | Example |
|---|---|---|
$count | Count records | { total: { $count: '*' } } |
$sum | Sum of values | { revenue: { $sum: 'amount' } } |
$avg | Average value | { avg_price: { $avg: 'price' } } |
$min | Minimum value | { lowest: { $min: 'price' } } |
$max | Maximum value | { highest: { $max: 'price' } } |
$stringAgg | Concatenate strings (PostgreSQL) | { names: { $stringAgg: { column: 'name', separator: ', ' } } } |
$groupConcat | Concatenate strings (MySQL) | { names: { $groupConcat: { column: 'name', separator: ', ' } } } |
$arrayAgg | Collect into array | { ids: { $arrayAgg: 'id' } } |
Uppercase operators (e.g., $COUNT, $SUM) are still supported for backwards compatibility, but lowercase is recommended.
Count
Count records with optional filtering:
Simple Count
- TypeScript
- Java
- Go
- .NET
const total = await ductape.database.count({
table: 'users',
});
console.log('Total users:', total);
Map<String, Object> total = ductape.database.count(Map.of(
"table", "users"
));
System.out.println('Total users:', total);
total := client.database.count({
"table": "users",
});
fmt.Println('Total users:', total);
var total = await ductape.database.count({
["table"] = "users",
});
Console.WriteLine('Total users:', total);
Count with Filter
- TypeScript
- Java
- Go
- .NET
const activeUsers = await ductape.database.count({
table: 'users',
where: { status: 'active' },
});
Map<String, Object> activeUsers = ductape.database.count(Map.of(
"table", "users",
where: Map.of( "status", "active" )
));
activeUsers := client.database.count({
"table": "users",
where: { "status": "active" },
});
var activeUsers = await ductape.database.count({
["table"] = "users",
where: { ["status"] = "active" },
});
Count Distinct Values
- TypeScript
- Java
- Go
- .NET
const uniqueCategories = await ductape.database.count({
table: 'products',
column: 'category',
distinct: true,
});
Map<String, Object> uniqueCategories = ductape.database.count(Map.of(
"table", "products",
"column", "category",
"distinct", true
));
uniqueCategories := client.database.count({
"table": "products",
"column": "category",
"distinct": true,
});
var uniqueCategories = await ductape.database.count({
["table"] = "products",
["column"] = "category",
["distinct"] = true,
});
Count Specific Column
Count non-null values in a column:
- TypeScript
- Java
- Go
- .NET
const usersWithEmail = await ductape.database.count({
table: 'users',
column: 'email', // Only counts rows where email is not null
});
Map<String, Object> usersWithEmail = ductape.database.count(Map.of(
"table", "users",
"column", "email", // Only counts rows where email is not null
));
usersWithEmail := client.database.count({
"table": "users",
"column": "email", // Only counts rows where email is not null
});
var usersWithEmail = await ductape.database.count({
["table"] = "users",
["column"] = "email", // Only counts rows where email is not null
});
Sum
Calculate the sum of numeric values:
- TypeScript
- Java
- Go
- .NET
const totalRevenue = await ductape.database.sum({
table: 'orders',
column: 'total',
where: { status: 'completed' },
});
console.log('Total revenue:', totalRevenue);
Map<String, Object> totalRevenue = ductape.database.sum(Map.of(
"table", "orders",
"column", "total",
where: Map.of( "status", "completed" )
));
System.out.println('Total revenue:', totalRevenue);
totalRevenue := client.database.sum({
"table": "orders",
"column": "total",
where: { "status": "completed" },
});
fmt.Println('Total revenue:', totalRevenue);
var totalRevenue = await ductape.database.sum({
["table"] = "orders",
["column"] = "total",
where: { ["status"] = "completed" },
});
Console.WriteLine('Total revenue:', totalRevenue);
Sum with Complex Filters
- TypeScript
- Java
- Go
- .NET
const monthlyRevenue = await ductape.database.sum({
table: 'orders',
column: 'total',
where: {
$and: [
{ status: 'completed' },
{ created_at: { $gte: new Date('2024-01-01') } },
{ created_at: { $lt: new Date('2024-02-01') } },
],
},
});
Map<String, Object> monthlyRevenue = ductape.database.sum(Map.of(
"table", "orders",
"column", "total",
where: Map.of(
$and: [
Map.of( "status", "completed" ),
Map.of( created_at: Map.of( $gte: new Date('2024-01-01') ) ),
Map.of( created_at: Map.of( $lt: new Date('2024-02-01') ) ),
]
)
));
monthlyRevenue := client.database.sum({
"table": "orders",
"column": "total",
where: {
$and: [
{ "status": "completed" },
{ created_at: { $gte: new Date('2024-01-01') } },
{ created_at: { $lt: new Date('2024-02-01') } },
],
},
});
var monthlyRevenue = await ductape.database.sum({
["table"] = "orders",
["column"] = "total",
where: {
$and: [
{ ["status"] = "completed" },
{ created_at: { $gte: new Date('2024-01-01') } },
{ created_at: { $lt: new Date('2024-02-01') } },
],
},
});
Average
Calculate the average of numeric values:
- TypeScript
- Java
- Go
- .NET
const avgOrderValue = await ductape.database.avg({
table: 'orders',
column: 'total',
where: { status: 'completed' },
});
console.log('Average order value:', avgOrderValue);
Map<String, Object> avgOrderValue = ductape.database.avg(Map.of(
"table", "orders",
"column", "total",
where: Map.of( "status", "completed" )
));
System.out.println('Average order value:', avgOrderValue);
avgOrderValue := client.database.avg({
"table": "orders",
"column": "total",
where: { "status": "completed" },
});
fmt.Println('Average order value:', avgOrderValue);
var avgOrderValue = await ductape.database.avg({
["table"] = "orders",
["column"] = "total",
where: { ["status"] = "completed" },
});
Console.WriteLine('Average order value:', avgOrderValue);
Min / Max
Find minimum or maximum values:
- TypeScript
- Java
- Go
- .NET
// Minimum value
const lowestPrice = await ductape.database.min({
table: 'products',
column: 'price',
where: { status: 'active' },
});
// Maximum value
const highestPrice = await ductape.database.max({
table: 'products',
column: 'price',
where: { status: 'active' },
});
console.log('Price range:', lowestPrice, '-', highestPrice);
// Minimum value
Map<String, Object> lowestPrice = ductape.database.min(Map.of(
"table", "products",
"column", "price",
where: Map.of( "status", "active" )
));
// Maximum value
Map<String, Object> highestPrice = ductape.database.max(Map.of(
"table", "products",
"column", "price",
where: Map.of( "status", "active" )
));
System.out.println('Price "range", ", lowestPrice, "-', highestPrice);
// Minimum value
lowestPrice := client.database.min({
"table": "products",
"column": "price",
where: { "status": "active" },
});
// Maximum value
highestPrice := client.database.max({
"table": "products",
"column": "price",
where: { "status": "active" },
});
fmt.Println('Price "range": ", lowestPrice, "-', highestPrice);
// Minimum value
var lowestPrice = await ductape.database.min({
["table"] = "products",
["column"] = "price",
where: { ["status"] = "active" },
});
// Maximum value
var highestPrice = await ductape.database.max({
["table"] = "products",
["column"] = "price",
where: { ["status"] = "active" },
});
Console.WriteLine('Price ["range"] = ", lowestPrice, "-', highestPrice);
Multi-Aggregation
Perform multiple aggregations in a single query:
- TypeScript
- Java
- Go
- .NET
const stats = await ductape.database.aggregate({
table: 'orders',
operations: {
total_orders: { $count: '*' },
total_revenue: { $sum: 'total' },
avg_order_value: { $avg: 'total' },
min_order: { $min: 'total' },
max_order: { $max: 'total' },
},
where: { status: 'completed' },
});
console.log('Statistics:', stats);
// {
// total_orders: 1234,
// total_revenue: 98765.43,
// avg_order_value: 80.04,
// min_order: 10.00,
// max_order: 500.00
// }
Map<String, Object> stats = ductape.database.aggregate(Map.of(
"table", "orders",
operations: Map.of(
total_orders: Map.of( $"count", "*" ),
total_revenue: Map.of( $"sum", "total" ),
avg_order_value: Map.of( $"avg", "total" ),
min_order: Map.of( $"min", "total" ),
max_order: Map.of( $"max", "total" )
),
where: Map.of( "status", "completed" )
));
System.out.println('Statistics:', stats);
// Map.of(
// "total_orders", 1234,
// "total_revenue", 98765.43,
// "avg_order_value", 80.04,
// "min_order", 10.00,
// "max_order", 500.00
// )
stats := client.database.aggregate({
"table": "orders",
operations: {
total_orders: { $"count": "*" },
total_revenue: { $"sum": "total" },
avg_order_value: { $"avg": "total" },
min_order: { $"min": "total" },
max_order: { $"max": "total" },
},
where: { "status": "completed" },
});
fmt.Println('Statistics:', stats);
// {
// "total_orders": 1234,
// "total_revenue": 98765.43,
// "avg_order_value": 80.04,
// "min_order": 10.00,
// "max_order": 500.00
// }
var stats = await ductape.database.aggregate({
["table"] = "orders",
operations: {
total_orders: { $["count"] = "*" },
total_revenue: { $["sum"] = "total" },
avg_order_value: { $["avg"] = "total" },
min_order: { $["min"] = "total" },
max_order: { $["max"] = "total" },
},
where: { ["status"] = "completed" },
});
Console.WriteLine('Statistics:', stats);
// {
// ["total_orders"] = 1234,
// ["total_revenue"] = 98765.43,
// ["avg_order_value"] = 80.04,
// ["min_order"] = 10.00,
// ["max_order"] = 500.00
// }
Group By
Group records and aggregate within each group:
Basic Group By
- TypeScript
- Java
- Go
- .NET
const result = await ductape.database.groupBy({
table: 'orders',
groupBy: ['status'],
aggregate: {
count: { $count: '*' },
total: { $sum: 'total' },
},
});
result.forEach((group) => {
console.log(`${group.status}: ${group.count} orders, $${group.total}`);
});
// pending: 50 orders, $2500
// completed: 200 orders, $15000
// cancelled: 10 orders, $500
Map<String, Object> result = ductape.database.groupBy(Map.of(
"table", "orders",
groupBy: ['status'],
aggregate: Map.of(
count: Map.of( $"count", "*" ),
total: Map.of( $"sum", "total" )
)
));
result.forEach((group) => Map.of(
System.out.println(`$Map.of(group.status): $Map.of(group.count) orders, $$Map.of(group.total)`);
));
// "pending", 50 orders, $2500
// "completed", 200 orders, $15000
// "cancelled", 10 orders, $500
result := client.database.groupBy({
"table": "orders",
groupBy: ['status'],
aggregate: {
count: { $"count": "*" },
total: { $"sum": "total" },
},
});
result.forEach((group) => {
fmt.Println(`${group.status}: ${group.count} orders, $${group.total}`);
});
// "pending": 50 orders, $2500
// "completed": 200 orders, $15000
// "cancelled": 10 orders, $500
var result = await ductape.database.groupBy({
["table"] = "orders",
groupBy: ['status'],
aggregate: {
count: { $["count"] = "*" },
total: { $["sum"] = "total" },
},
});
result.forEach((group) => {
Console.WriteLine(`${group.status}: ${group.count} orders, $${group.total}`);
});
// ["pending"] = 50 orders, $2500
// ["completed"] = 200 orders, $15000
// ["cancelled"] = 10 orders, $500
Multiple Group By Columns
- TypeScript
- Java
- Go
- .NET
const result = await ductape.database.groupBy({
table: 'orders',
groupBy: ['status', 'payment_method'],
aggregate: {
total_orders: { $count: '*' },
total_amount: { $sum: 'total' },
avg_amount: { $avg: 'total' },
},
});
result.forEach((group) => {
console.log('Status:', group.status);
console.log('Payment Method:', group.payment_method);
console.log('Total Orders:', group.total_orders);
console.log('Total Amount:', group.total_amount);
console.log('---');
});
Map<String, Object> result = ductape.database.groupBy(Map.of(
"table", "orders",
groupBy: ['status', 'payment_method'],
aggregate: Map.of(
total_orders: Map.of( $"count", "*" ),
total_amount: Map.of( $"sum", "total" ),
avg_amount: Map.of( $"avg", "total" )
)
));
result.forEach((group) => Map.of(
System.out.println('"Status", ", group.status);
System.out.println("Payment "Method", ", group.payment_method);
System.out.println("Total "Orders", ", group.total_orders);
System.out.println("Total "Amount", ", group.total_amount);
System.out.println("---');
));
result := client.database.groupBy({
"table": "orders",
groupBy: ['status', 'payment_method'],
aggregate: {
total_orders: { $"count": "*" },
total_amount: { $"sum": "total" },
avg_amount: { $"avg": "total" },
},
});
result.forEach((group) => {
fmt.Println('"Status": ", group.status);
fmt.Println("Payment "Method": ", group.payment_method);
fmt.Println("Total "Orders": ", group.total_orders);
fmt.Println("Total "Amount": ", group.total_amount);
fmt.Println("---');
});
var result = await ductape.database.groupBy({
["table"] = "orders",
groupBy: ['status', 'payment_method'],
aggregate: {
total_orders: { $["count"] = "*" },
total_amount: { $["sum"] = "total" },
avg_amount: { $["avg"] = "total" },
},
});
result.forEach((group) => {
Console.WriteLine('["Status"] = ", group.status);
Console.WriteLine("Payment ["Method"] = ", group.payment_method);
Console.WriteLine("Total ["Orders"] = ", group.total_orders);
Console.WriteLine("Total ["Amount"] = ", group.total_amount);
Console.WriteLine("---');
});
Group By with Filters
- TypeScript
- Java
- Go
- .NET
const result = await ductape.database.groupBy({
table: 'orders',
groupBy: ['category'],
aggregate: {
count: { $count: '*' },
revenue: { $sum: 'total' },
},
where: {
created_at: { $gte: new Date('2024-01-01') },
status: 'completed',
},
});
Map<String, Object> result = ductape.database.groupBy(Map.of(
"table", "orders",
groupBy: ['category'],
aggregate: Map.of(
count: Map.of( $"count", "*" ),
revenue: Map.of( $"sum", "total" )
),
where: Map.of(
created_at: Map.of( $gte: new Date('2024-01-01') ),
"status", "completed"
)
));
result := client.database.groupBy({
"table": "orders",
groupBy: ['category'],
aggregate: {
count: { $"count": "*" },
revenue: { $"sum": "total" },
},
where: {
created_at: { $gte: new Date('2024-01-01') },
"status": "completed",
},
});
var result = await ductape.database.groupBy({
["table"] = "orders",
groupBy: ['category'],
aggregate: {
count: { $["count"] = "*" },
revenue: { $["sum"] = "total" },
},
where: {
created_at: { $gte: new Date('2024-01-01') },
["status"] = "completed",
},
});
Group By with HAVING
Filter groups after aggregation:
- TypeScript
- Java
- Go
- .NET
const result = await ductape.database.groupBy({
table: 'orders',
groupBy: ['customer_id'],
aggregate: {
order_count: { $count: '*' },
total_spent: { $sum: 'total' },
},
having: {
order_count: { $gt: 10 }, // Customers with more than 10 orders
total_spent: { $gte: 1000 }, // Who spent at least $1000
},
});
Map<String, Object> result = ductape.database.groupBy(Map.of(
"table", "orders",
groupBy: ['customer_id'],
aggregate: Map.of(
order_count: Map.of( $"count", "*" ),
total_spent: Map.of( $"sum", "total" )
),
having: Map.of(
order_count: Map.of( $"gt", 10 ), // Customers with more than 10 orders
total_spent: Map.of( $"gte", 1000 ), // Who spent at least $1000
)
));
result := client.database.groupBy({
"table": "orders",
groupBy: ['customer_id'],
aggregate: {
order_count: { $"count": "*" },
total_spent: { $"sum": "total" },
},
having: {
order_count: { $"gt": 10 }, // Customers with more than 10 orders
total_spent: { $"gte": 1000 }, // Who spent at least $1000
},
});
var result = await ductape.database.groupBy({
["table"] = "orders",
groupBy: ['customer_id'],
aggregate: {
order_count: { $["count"] = "*" },
total_spent: { $["sum"] = "total" },
},
having: {
order_count: { $["gt"] = 10 }, // Customers with more than 10 orders
total_spent: { $["gte"] = 1000 }, // Who spent at least $1000
},
});
Group By with Ordering
- TypeScript
- Java
- Go
- .NET
const result = await ductape.database.groupBy({
table: 'products',
groupBy: ['category'],
aggregate: {
product_count: { $count: '*' },
avg_price: { $avg: 'price' },
},
orderBy: { column: 'product_count', order: 'DESC' },
limit: 10, // Top 10 categories
});
Map<String, Object> result = ductape.database.groupBy(Map.of(
"table", "products",
groupBy: ['category'],
aggregate: Map.of(
product_count: Map.of( $"count", "*" ),
avg_price: Map.of( $"avg", "price" )
),
orderBy: Map.of( "column", "product_count", "order", "DESC" ),
"limit", 10, // Top 10 categories
));
result := client.database.groupBy({
"table": "products",
groupBy: ['category'],
aggregate: {
product_count: { $"count": "*" },
avg_price: { $"avg": "price" },
},
orderBy: { "column": "product_count", "order": "DESC" },
"limit": 10, // Top 10 categories
});
var result = await ductape.database.groupBy({
["table"] = "products",
groupBy: ['category'],
aggregate: {
product_count: { $["count"] = "*" },
avg_price: { $["avg"] = "price" },
},
orderBy: { ["column"] = "product_count", ["order"] = "DESC" },
["limit"] = 10, // Top 10 categories
});
Database-Specific Functions
PostgreSQL
- TypeScript
- Java
- Go
- .NET
// String aggregation
const result = await ductape.database.groupBy({
table: 'orders',
groupBy: ['customer_id'],
aggregate: {
order_ids: { $stringAgg: { column: 'id', separator: ', ' } }, // "1, 2, 3, 4"
products: { $arrayAgg: 'product_id' }, // [1, 2, 3, 4]
},
});
// String aggregation
Map<String, Object> result = ductape.database.groupBy(Map.of(
"table", "orders",
groupBy: ['customer_id'],
aggregate: Map.of(
order_ids: Map.of( $stringAgg: Map.of( "column", "id", "separator", ", " ) ), // "1, 2, 3, 4"
products: Map.of( $"arrayAgg", "product_id" ), // [1, 2, 3, 4]
)
));
// String aggregation
result := client.database.groupBy({
"table": "orders",
groupBy: ['customer_id'],
aggregate: {
order_ids: { $stringAgg: { "column": "id", "separator": ", " } }, // "1, 2, 3, 4"
products: { $"arrayAgg": "product_id" }, // [1, 2, 3, 4]
},
});
// String aggregation
var result = await ductape.database.groupBy({
["table"] = "orders",
groupBy: ['customer_id'],
aggregate: {
order_ids: { $stringAgg: { ["column"] = "id", ["separator"] = ", " } }, // "1, 2, 3, 4"
products: { $["arrayAgg"] = "product_id" }, // [1, 2, 3, 4]
},
});
MySQL
- TypeScript
- Java
- Go
- .NET
// Group concatenation
const result = await ductape.database.groupBy({
table: 'orders',
groupBy: ['customer_id'],
aggregate: {
product_names: { $groupConcat: { column: 'product_name', separator: ',' } }, // "Product A,Product B,Product C"
},
});
// Group concatenation
Map<String, Object> result = ductape.database.groupBy(Map.of(
"table", "orders",
groupBy: ['customer_id'],
aggregate: Map.of(
product_names: Map.of( $groupConcat: Map.of( "column", "product_name", "separator", "," ) ), // "Product A,Product B,Product C"
)
));
// Group concatenation
result := client.database.groupBy({
"table": "orders",
groupBy: ['customer_id'],
aggregate: {
product_names: { $groupConcat: { "column": "product_name", "separator": "," } }, // "Product A,Product B,Product C"
},
});
// Group concatenation
var result = await ductape.database.groupBy({
["table"] = "orders",
groupBy: ['customer_id'],
aggregate: {
product_names: { $groupConcat: { ["column"] = "product_name", ["separator"] = "," } }, // "Product A,Product B,Product C"
},
});
MongoDB
- TypeScript
- Java
- Go
- .NET
// Push to array (equivalent to $arrayAgg)
const result = await ductape.database.groupBy({
table: 'orders', // Collection name
groupBy: ['customer_id'],
aggregate: {
order_ids: { $arrayAgg: '_id' },
total_spent: { $sum: 'total' },
},
});
// Push to array (equivalent to $arrayAgg)
Map<String, Object> result = ductape.database.groupBy(Map.of(
"table", "orders", // Collection name
groupBy: ['customer_id'],
aggregate: Map.of(
order_ids: Map.of( $"arrayAgg", "_id" ),
total_spent: Map.of( $"sum", "total" )
)
));
// Push to array (equivalent to $arrayAgg)
result := client.database.groupBy({
"table": "orders", // Collection name
groupBy: ['customer_id'],
aggregate: {
order_ids: { $"arrayAgg": "_id" },
total_spent: { $"sum": "total" },
},
});
// Push to array (equivalent to $arrayAgg)
var result = await ductape.database.groupBy({
["table"] = "orders", // Collection name
groupBy: ['customer_id'],
aggregate: {
order_ids: { $["arrayAgg"] = "_id" },
total_spent: { $["sum"] = "total" },
},
});
Use Cases
Dashboard Statistics
- TypeScript
- Java
- Go
- .NET
async function getDashboardStats() {
const [orderStats, userStats, productStats] = await Promise.all([
ductape.database.aggregate({
table: 'orders',
operations: {
total_orders: { $count: '*' },
total_revenue: { $sum: 'total' },
avg_order: { $avg: 'total' },
},
where: {
created_at: { $gte: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) },
},
}),
ductape.database.count({
table: 'users',
where: {
created_at: { $gte: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) },
},
}),
ductape.database.count({
table: 'products',
where: { status: 'active' },
}),
]);
return {
orders: orderStats,
newUsers: userStats,
activeProducts: productStats,
};
}
async function getDashboardStats() Map.of(
Map<String, Object> [orderStats, userStats, productStats] = Promise.all([
ductape.database.aggregate(Map.of(
"table", "orders",
operations: Map.of(
total_orders: Map.of( $"count", "*" ),
total_revenue: Map.of( $"sum", "total" ),
avg_order: Map.of( $"avg", "total" )
),
where: Map.of(
created_at: Map.of( $gte: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) )
)
)),
ductape.database.count(Map.of(
"table", "users",
where: Map.of(
created_at: Map.of( $gte: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) )
)
)),
ductape.database.count(Map.of(
"table", "products",
where: Map.of( "status", "active" )
)),
]);
return Map.of(
orders: orderStats,
newUsers: userStats,
activeProducts: productStats
);
)
async function getDashboardStats() {
const [orderStats, userStats, productStats] = Promise.all([
client.database.aggregate({
"table": "orders",
operations: {
total_orders: { $"count": "*" },
total_revenue: { $"sum": "total" },
avg_order: { $"avg": "total" },
},
where: {
created_at: { $gte: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) },
},
}),
client.database.count({
"table": "users",
where: {
created_at: { $gte: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) },
},
}),
client.database.count({
"table": "products",
where: { "status": "active" },
}),
]);
return {
orders: orderStats,
newUsers: userStats,
activeProducts: productStats,
};
}
async function getDashboardStats() {
var [orderStats, userStats, productStats] = await Promise.all([
ductape.database.aggregate({
["table"] = "orders",
operations: {
total_orders: { $["count"] = "*" },
total_revenue: { $["sum"] = "total" },
avg_order: { $["avg"] = "total" },
},
where: {
created_at: { $gte: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) },
},
}),
ductape.database.count({
["table"] = "users",
where: {
created_at: { $gte: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) },
},
}),
ductape.database.count({
["table"] = "products",
where: { ["status"] = "active" },
}),
]);
return {
orders: orderStats,
newUsers: userStats,
activeProducts: productStats,
};
}
Sales by Category
- TypeScript
- Java
- Go
- .NET
async function getSalesByCategory(startDate: Date, endDate: Date) {
return ductape.database.groupBy({
table: 'order_items',
groupBy: ['category'],
aggregate: {
units_sold: { $sum: 'quantity' },
revenue: { $sum: 'total' },
avg_price: { $avg: 'unit_price' },
},
where: {
created_at: { $between: [startDate, endDate] },
},
orderBy: { column: 'revenue', order: 'DESC' },
});
}
async function getSalesByCategory(startDate: Date, endDate: Date) Map.of(
return ductape.database.groupBy(Map.of(
"table", "order_items",
groupBy: ['category'],
aggregate: Map.of(
units_sold: Map.of( $"sum", "quantity" ),
revenue: Map.of( $"sum", "total" ),
avg_price: Map.of( $"avg", "unit_price" )
),
where: Map.of(
created_at: Map.of( $between: [startDate, endDate] )
),
orderBy: Map.of( "column", "revenue", "order", "DESC" )
));
)
async function getSalesByCategory(startDate: Date, endDate: Date) {
return client.database.groupBy({
"table": "order_items",
groupBy: ['category'],
aggregate: {
units_sold: { $"sum": "quantity" },
revenue: { $"sum": "total" },
avg_price: { $"avg": "unit_price" },
},
where: {
created_at: { $between: [startDate, endDate] },
},
orderBy: { "column": "revenue", "order": "DESC" },
});
}
async function getSalesByCategory(startDate: Date, endDate: Date) {
return ductape.database.groupBy({
["table"] = "order_items",
groupBy: ['category'],
aggregate: {
units_sold: { $["sum"] = "quantity" },
revenue: { $["sum"] = "total" },
avg_price: { $["avg"] = "unit_price" },
},
where: {
created_at: { $between: [startDate, endDate] },
},
orderBy: { ["column"] = "revenue", ["order"] = "DESC" },
});
}
Top Customers
- TypeScript
- Java
- Go
- .NET
async function getTopCustomers(limit: number = 10) {
return ductape.database.groupBy({
table: 'orders',
groupBy: ['customer_id'],
aggregate: {
order_count: { $count: '*' },
total_spent: { $sum: 'total' },
avg_order: { $avg: 'total' },
first_order: { $min: 'created_at' },
last_order: { $max: 'created_at' },
},
where: { status: 'completed' },
orderBy: { column: 'total_spent', order: 'DESC' },
limit,
});
}
async function getTopCustomers(limit: number = 10) Map.of(
return ductape.database.groupBy(Map.of(
"table", "orders",
groupBy: ['customer_id'],
aggregate: Map.of(
order_count: Map.of( $"count", "*" ),
total_spent: Map.of( $"sum", "total" ),
avg_order: Map.of( $"avg", "total" ),
first_order: Map.of( $"min", "created_at" ),
last_order: Map.of( $"max", "created_at" )
),
where: Map.of( "status", "completed" ),
orderBy: Map.of( "column", "total_spent", "order", "DESC" ),
limit
));
)
async function getTopCustomers(limit: number = 10) {
return client.database.groupBy({
"table": "orders",
groupBy: ['customer_id'],
aggregate: {
order_count: { $"count": "*" },
total_spent: { $"sum": "total" },
avg_order: { $"avg": "total" },
first_order: { $"min": "created_at" },
last_order: { $"max": "created_at" },
},
where: { "status": "completed" },
orderBy: { "column": "total_spent", "order": "DESC" },
limit,
});
}
async function getTopCustomers(limit: number = 10) {
return ductape.database.groupBy({
["table"] = "orders",
groupBy: ['customer_id'],
aggregate: {
order_count: { $["count"] = "*" },
total_spent: { $["sum"] = "total" },
avg_order: { $["avg"] = "total" },
first_order: { $["min"] = "created_at" },
last_order: { $["max"] = "created_at" },
},
where: { ["status"] = "completed" },
orderBy: { ["column"] = "total_spent", ["order"] = "DESC" },
limit,
});
}
Daily Revenue Report
- TypeScript
- Java
- Go
- .NET
async function getDailyRevenue(days: number = 30) {
// Note: Date grouping requires raw query for some databases
return ductape.database.raw({
query: `
SELECT
DATE(created_at) as date,
COUNT(*) as order_count,
SUM(total) as revenue,
AVG(total) as avg_order
FROM orders
WHERE created_at >= $1 AND status = 'completed'
GROUP BY DATE(created_at)
ORDER BY date DESC
`,
params: [new Date(Date.now() - days * 24 * 60 * 60 * 1000)],
});
}
async function getDailyRevenue(days: number = 30) Map.of(
// Note: Date grouping requires raw query for some databases
return ductape.database.raw(Map.of(
query: `
SELECT
DATE(created_at) as date,
COUNT(*) as order_count,
SUM(total) as revenue,
AVG(total) as avg_order
FROM orders
WHERE created_at >= $1 AND status = 'completed'
GROUP BY DATE(created_at)
ORDER BY date DESC
`,
params: [new Date(Date.now() - days * 24 * 60 * 60 * 1000)]
));
)
async function getDailyRevenue(days: number = 30) {
// Note: Date grouping requires raw query for some databases
return client.database.raw({
query: `
SELECT
DATE(created_at) as date,
COUNT(*) as order_count,
SUM(total) as revenue,
AVG(total) as avg_order
FROM orders
WHERE created_at >= $1 AND status = 'completed'
GROUP BY DATE(created_at)
ORDER BY date DESC
`,
params: [new Date(Date.now() - days * 24 * 60 * 60 * 1000)],
});
}
async function getDailyRevenue(days: number = 30) {
// Note: Date grouping requires raw query for some databases
return ductape.database.raw({
query: `
SELECT
DATE(created_at) as date,
COUNT(*) as order_count,
SUM(total) as revenue,
AVG(total) as avg_order
FROM orders
WHERE created_at >= $1 AND status = 'completed'
GROUP BY DATE(created_at)
ORDER BY date DESC
`,
params: [new Date(Date.now() - days * 24 * 60 * 60 * 1000)],
});
}
Aggregation Options Reference
Count Options
| Option | Type | Description |
|---|---|---|
table | string | Table name |
column | string | Column to count (default: *) |
where | object | Filter conditions |
distinct | boolean | Count distinct values |
Sum/Avg/Min/Max Options
| Option | Type | Description |
|---|---|---|
table | string | Table name |
column | string | Column to aggregate |
where | object | Filter conditions |
Aggregate Options
| Option | Type | Description |
|---|---|---|
table | string | Table name |
operations | object | Aggregation operations |
where | object | Filter conditions |
groupBy | string[] | Group by columns |
having | object | Filter aggregated groups |
Group By Options
| Option | Type | Description |
|---|---|---|
table | string | Table name |
groupBy | string[] | Columns to group by |
aggregate | object | Aggregation operations |
where | object | Filter conditions (before grouping) |
having | object | Filter conditions (after grouping) |
orderBy | object | Sort configuration |
limit | number | Maximum groups to return |
offset | number | Groups to skip |
Performance Considerations
DynamoDB Warning
DynamoDB does not support native aggregations. Ductape emulates aggregations by scanning the entire table into memory. For large tables, this can be:
- Slow - Full table scan required
- Expensive - Consumes read capacity
- Memory intensive - All data loaded into memory
For DynamoDB, consider:
- Maintaining pre-computed aggregates
- Using AWS Athena for analytics
- Limiting aggregations to filtered subsets
Indexing
Ensure columns used in WHERE and GROUP BY are properly indexed:
- TypeScript
- Java
- Go
- .NET
// Create index for common aggregation patterns
await ductape.database.createIndex({
table: 'orders',
index: {
name: 'idx_orders_status_created',
table: 'orders',
columns: [
{ name: 'status' },
{ name: 'created_at', order: 'DESC' },
],
},
});
// Create index for common aggregation patterns
ductape.database.createIndex(Map.of(
"table", "orders",
index: Map.of(
"name", "idx_orders_status_created",
"table", "orders",
columns: [
Map.of( "name", "status" ),
Map.of( "name", "created_at", "order", "DESC" ),
]
)
));
// Create index for common aggregation patterns
client.database.createIndex({
"table": "orders",
index: {
"name": "idx_orders_status_created",
"table": "orders",
columns: [
{ "name": "status" },
{ "name": "created_at", "order": "DESC" },
],
},
});
// Create index for common aggregation patterns
await ductape.database.createIndex({
["table"] = "orders",
index: {
["name"] = "idx_orders_status_created",
["table"] = "orders",
columns: [
{ ["name"] = "status" },
{ ["name"] = "created_at", ["order"] = "DESC" },
],
},
});
Next Steps
- Transactions - Use aggregations within transactions
- Best Practices - Performance optimization tips
- Direct Queries - Raw SQL for complex aggregations