Skip to content

Aggregate API 聚合统计查询


v1.2.0+

aggregate API 是 Lovrabet SDK 提供的数据聚合统计接口,支持 SUM、COUNT、AVG 等聚合函数,配合 GROUP BY、HAVING 实现复杂的数据统计分析,是构建报表和数据大屏的核心工具。

💡 前置条件开始之前,请确保已完成 SDK 配置。推荐使用 CLI 自动生成配置。

以下示例使用别名方式 client.models.orders 以便阅读,也可以使用标准方式 client.models.dataset_xxx(功能完全一致)。

⚠️ 操作限制aggregate() 操作仅 WebAPI 模式(Cookie 认证)支持。OpenAPI 模式暂不支持此功能。

🎯 主要功能

  • 聚合函数 - 支持 SUM(求和)、COUNT(计数)、AVG(平均值)
  • 分组统计 - GROUP BY 分组聚合
  • 条件筛选 - WHERE 条件过滤 + HAVING 分组后过滤
  • 结果排序 - 支持按聚合结果排序
  • 分页支持 - 大数据量分组结果的分页
  • 精度控制 - 四舍五入、小数位数设置

📝 API 签名

TypeScript
async aggregate<T = any>(params: AggregateParams): Promise<T | T[]>

参数说明

TypeScript
interface AggregateParams {
  select?: string[];              // 选择返回的字段(通常用于 GROUP BY)
  aggregate: AggregateField[];    // 聚合配置(必填)
  where?: WhereCondition;         // 查询条件(聚合前过滤)
  groupBy?: string[];             // 分组字段
  having?: HavingCondition[];     // 分组后过滤条件
  orderBy?: SortList;             // 排序规则
  currentPage?: number;           // 当前页码
  pageSize?: number;              // 每页数量
}

聚合字段配置

TypeScript
interface AggregateField {
  type: 'SUM' | 'COUNT' | 'AVG' | 'MIN' | 'MAX';  // 聚合类型
  column: string;              // 字段名(COUNT 用 '*' 表示所有)
  alias?: string;              // 返回结果的字段别名
  distinct?: boolean;          // 是否去重(COUNT DISTINCT)
  round?: boolean;             // 是否四舍五入
  precision?: number;          // 小数位数(配合 round 使用)
  /** @deprecated v1.4.2 起改用 column;SDK 会把 field 自动归一化为 column */
  field?: string;
}

💡 fieldcolumn(v1.4.2):聚合字段名以 column 为标准入参,请求体统一向后端发送 column。旧的 field 写法仍完全兼容(SDK 自动归一化),本文示例中的 field 均可直接替换为 column,新代码推荐用 column

返回值

  • 无 GROUP BY:返回单个对象 { alias1: value1, alias2: value2 }
  • 有 GROUP BY:返回数组 [{ groupField: value, alias1: value1 }, ...]

📊 聚合函数详解

SUM(求和)

计算指定字段的总和,适用于数值类型字段。

TypeScript
// 计算订单总金额
const result = await client.models.orders.aggregate({
  aggregate: [
    { type: 'SUM', field: 'total_amount', alias: 'total_sales' },
  ],
});

console.log(result);
// { total_sales: 125678.90 }

COUNT(计数)

统计记录数量。

TypeScript
// 统计订单总数
const result = await client.models.orders.aggregate({
  aggregate: [
    { type: 'COUNT', field: '*', alias: 'total_count' },
  ],
});

console.log(result);
// { total_count: 1250 }

// 统计不重复的客户数
const result = await client.models.orders.aggregate({
  aggregate: [
    { type: 'COUNT', field: 'customer_id', alias: 'unique_customers', distinct: true },
  ],
});

console.log(result);
// { unique_customers: 320 }

AVG(平均值)

计算指定字段的平均值。

TypeScript
// 计算平均订单金额
const result = await client.models.orders.aggregate({
  aggregate: [
    { type: 'AVG', field: 'total_amount', alias: 'avg_amount', round: true, precision: 2 },
  ],
});

console.log(result);
// { avg_amount: 125.45 }

多个聚合函数组合

TypeScript
// 同时获取总数、总和、平均值
const stats = await client.models.orders.aggregate({
  aggregate: [
    { type: 'COUNT', field: '*', alias: 'order_count' },
    { type: 'SUM', field: 'total_amount', alias: 'total_sales', round: true, precision: 2 },
    { type: 'AVG', field: 'total_amount', alias: 'avg_amount', round: true, precision: 2 },
  ],
});

console.log(stats);
// { order_count: 1250, total_sales: 156789.50, avg_amount: 125.43 }

🔀 GROUP BY 分组聚合

基础分组

TypeScript
// 按状态分组统计订单
const result = await client.models.orders.aggregate({
  select: ['status'],
  aggregate: [
    { type: 'COUNT', field: '*', alias: 'count' },
    { type: 'SUM', field: 'total_amount', alias: 'total' },
  ],
  groupBy: ['status'],
});

console.log(result);
// [
//   { status: 'pending', count: 45, total: 5678.00 },
//   { status: 'completed', count: 1200, total: 145678.50 },
//   { status: 'cancelled', count: 5, total: 433.00 },
// ]

多字段分组

TypeScript
// 按年份和月份分组统计
const result = await client.models.orders.aggregate({
  select: ['year', 'month'],
  aggregate: [
    { type: 'COUNT', field: '*', alias: 'order_count' },
    { type: 'SUM', field: 'total_amount', alias: 'total_sales' },
  ],
  groupBy: ['year', 'month'],
  orderBy: [{ year: 'desc' }, { month: 'desc' }],
});

console.log(result);
// [
//   { year: 2025, month: 2, order_count: 150, total_sales: 18765.00 },
//   { year: 2025, month: 1, order_count: 200, total_sales: 25432.00 },
//   { year: 2024, month: 12, order_count: 180, total_sales: 22100.00 },
// ]

按分类统计

TypeScript
// 按产品分类统计销量
const result = await client.models.order_items.aggregate({
  select: ['category_name'],
  aggregate: [
    { type: 'COUNT', field: '*', alias: 'item_count' },
    { type: 'SUM', field: 'quantity', alias: 'total_quantity' },
    { type: 'SUM', field: 'subtotal', alias: 'total_revenue' },
  ],
  groupBy: ['category_name'],
  orderBy: [{ total_revenue: 'desc' }],
});

console.log(result);
// [
//   { category_name: '电子产品', item_count: 500, total_quantity: 800, total_revenue: 456789.00 },
//   { category_name: '服装', item_count: 300, total_quantity: 1200, total_revenue: 123456.00 },
// ]

🔍 WHERE 条件过滤

在聚合前先过滤数据,只对符合条件的数据进行统计。

TypeScript
// 统计已完成订单
const result = await client.models.orders.aggregate({
  aggregate: [
    { type: 'COUNT', field: '*', alias: 'completed_count' },
    { type: 'SUM', field: 'total_amount', alias: 'completed_total' },
  ],
  where: {
    status: { $eq: 'completed' },
  },
});

console.log(result);
// { completed_count: 1200, completed_total: 145678.50 }

// 统计指定日期范围内的订单
const result = await client.models.orders.aggregate({
  select: ['status'],
  aggregate: [
    { type: 'COUNT', field: '*', alias: 'count' },
    { type: 'SUM', field: 'total_amount', alias: 'total' },
  ],
  where: {
    create_time: { $gte: '2025-01-01', $lte: '2025-01-31' },
    status: { $in: ['completed', 'shipped'] },
  },
  groupBy: ['status'],
});

🎯 HAVING 分组后过滤

HAVING 用于对聚合结果进行过滤,类似于 WHERE 但作用于分组后的结果。

TypeScript
// 找出销售额超过 10000 的分类
const result = await client.models.orders.aggregate({
  select: ['category_id'],
  aggregate: [
    { type: 'SUM', field: 'total_amount', alias: 'total_sales' },
  ],
  groupBy: ['category_id'],
  having: [
    { columnName: 'total_sales', condition: { $gte: 10000 } },
  ],
  orderBy: [{ total_sales: 'desc' }],
});

console.log(result);
// [
//   { category_id: 1, total_sales: 45678.00 },
//   { category_id: 3, total_sales: 23456.00 },
// ]

// 多条件 HAVING
const result = await client.models.orders.aggregate({
  select: ['customer_id'],
  aggregate: [
    { type: 'COUNT', field: '*', alias: 'order_count' },
    { type: 'SUM', field: 'total_amount', alias: 'total_amount' },
  ],
  groupBy: ['customer_id'],
  having: [
    { columnName: 'order_count', condition: { $gte: 5 } },
    { columnName: 'total_amount', condition: { $gte: 1000 } },
  ],
});

// 找出订单数 >= 5 且总金额 >= 1000 的 VIP 客户

📋 分页

对于大量分组结果,可以使用分页。

TypeScript
// 分页获取分类销售排行
const result = await client.models.orders.aggregate({
  select: ['category_id'],
  aggregate: [
    { type: 'COUNT', field: '*', alias: 'order_count' },
    { type: 'SUM', field: 'total_amount', alias: 'total_sales' },
  ],
  groupBy: ['category_id'],
  orderBy: [{ total_sales: 'desc' }],
  currentPage: 1,
  pageSize: 10,
});

console.log(result);
// 返回前 10 个分类的统计结果

🎨 完整示例

示例 1:销售数据统计面板

TypeScript
import { client } from "./api/client";

async function getSalesDashboard() {
  // 1. 总体销售数据
  const overallStats = await client.models.orders.aggregate({
    aggregate: [
      { type: 'COUNT', field: '*', alias: 'total_orders' },
      { type: 'SUM', field: 'total_amount', alias: 'total_revenue', round: true, precision: 2 },
      { type: 'AVG', field: 'total_amount', alias: 'avg_order_value', round: true, precision: 2 },
    ],
    where: {
      status: { $eq: 'completed' },
    },
  });

  // 2. 按分类统计
  const categoryStats = await client.models.orders.aggregate({
    select: ['category_id', 'category_name'],
    aggregate: [
      { type: 'COUNT', field: '*', alias: 'order_count' },
      { type: 'SUM', field: 'total_amount', alias: 'category_revenue' },
    ],
    where: {
      status: { $eq: 'completed' },
    },
    groupBy: ['category_id', 'category_name'],
    orderBy: [{ category_revenue: 'desc' }],
    pageSize: 5,
  });

  // 3. 本月销售趋势
  const now = new Date();
  const monthStart = new Date(now.getFullYear(), now.getMonth(), 1).toISOString();

  const monthlyStats = await client.models.orders.aggregate({
    select: ['DATE(create_time) as date'],
    aggregate: [
      { type: 'COUNT', field: '*', alias: 'daily_orders' },
      { type: 'SUM', field: 'total_amount', alias: 'daily_revenue' },
    ],
    where: {
      create_time: { $gte: monthStart },
      status: { $eq: 'completed' },
    },
    groupBy: ['DATE(create_time)'],
    orderBy: [{ date: 'asc' }],
  });

  return {
    overall: overallStats,
    byCategory: categoryStats,
    monthlyTrend: monthlyStats,
  };
}

// 使用
const dashboard = await getSalesDashboard();
console.log('总体数据:', dashboard.overall);
console.log('分类排行:', dashboard.byCategory);
console.log('本月趋势:', dashboard.monthlyTrend);

示例 2:客户分析报表

TypeScript
// 客户消费分析
async function analyzeCustomers() {
  // 客户消费排名 TOP 10
  const topCustomers = await client.models.orders.aggregate({
    select: ['customer_id', 'customer_name'],
    aggregate: [
      { type: 'COUNT', field: '*', alias: 'order_count' },
      { type: 'SUM', field: 'total_amount', alias: 'total_spent' },
      { type: 'AVG', field: 'total_amount', alias: 'avg_order', round: true, precision: 2 },
    ],
    groupBy: ['customer_id', 'customer_name'],
    orderBy: [{ total_spent: 'desc' }],
    pageSize: 10,
  });

  // 客户分层统计
  const customerSegments = await client.models.customers.aggregate({
    select: ['level'],
    aggregate: [
      { type: 'COUNT', field: '*', alias: 'customer_count' },
      { type: 'SUM', field: 'total_purchases', alias: 'total_purchases' },
    ],
    groupBy: ['level'],
    orderBy: [{ customer_count: 'desc' }],
  });

  // 高价值客户(消费超过 5000)
  const vipCustomers = await client.models.orders.aggregate({
    select: ['customer_id'],
    aggregate: [
      { type: 'SUM', field: 'total_amount', alias: 'lifetime_value' },
    ],
    groupBy: ['customer_id'],
    having: [
      { columnName: 'lifetime_value', condition: { $gte: 5000 } },
    ],
    orderBy: [{ lifetime_value: 'desc' }],
  });

  return {
    topCustomers,
    segments: customerSegments,
    vipCount: vipCustomers.length,
  };
}

示例 3:React 组件集成

TypeScript
import { useState, useEffect } from "react";
import { client } from "./api/client";
import { Table, Card, Statistic, Row, Col } from "antd";

function SalesReport() {
  const [loading, setLoading] = useState(false);
  const [overallStats, setOverallStats] = useState<any>({});
  const [categoryData, setCategoryData] = useState<any[]>([]);

  useEffect(() => {
    loadReport();
  }, []);

  const loadReport = async () => {
    setLoading(true);
    try {
      // 总体统计
      const overall = await client.models.orders.aggregate({
        aggregate: [
          { type: 'COUNT', field: '*', alias: 'totalOrders' },
          { type: 'SUM', field: 'total_amount', alias: 'totalRevenue' },
          { type: 'AVG', field: 'total_amount', alias: 'avgOrderValue', round: true, precision: 2 },
        ],
        where: {
          status: { $eq: 'completed' },
        },
      });
      setOverallStats(overall);

      // 分类统计
      const byCategory = await client.models.orders.aggregate({
        select: ['category_name'],
        aggregate: [
          { type: 'COUNT', field: '*', alias: 'orderCount' },
          { type: 'SUM', field: 'total_amount', alias: 'revenue' },
        ],
        where: {
          status: { $eq: 'completed' },
        },
        groupBy: ['category_name'],
        orderBy: [{ revenue: 'desc' }],
      });
      setCategoryData(byCategory);
    } catch (error) {
      console.error("加载报表失败:", error);
    } finally {
      setLoading(false);
    }
  };

  const columns = [
    { title: "分类", dataIndex: "category_name", key: "category_name" },
    { title: "订单数", dataIndex: "orderCount", key: "orderCount" },
    {
      title: "销售额",
      dataIndex: "revenue",
      key: "revenue",
      render: (v: number) => `¥${v?.toLocaleString()}`,
    },
  ];

  return (
    <div>
      <Row gutter={16} style={{ marginBottom: 24 }}>
        <Col span={8}>
          <Card>
            <Statistic
              title="总订单数"
              value={overallStats.totalOrders}
              loading={loading}
            />
          </Card>
        </Col>
        <Col span={8}>
          <Card>
            <Statistic
              title="总销售额"
              value={overallStats.totalRevenue}
              precision={2}
              prefix="¥"
              loading={loading}
            />
          </Card>
        </Col>
        <Col span={8}>
          <Card>
            <Statistic
              title="平均订单金额"
              value={overallStats.avgOrderValue}
              precision={2}
              prefix="¥"
              loading={loading}
            />
          </Card>
        </Col>
      </Row>

      <Card title="分类销售排行">
        <Table
          dataSource={categoryData}
          columns={columns}
          rowKey="category_name"
          loading={loading}
          pagination={false}
        />
      </Card>
    </div>
  );
}

🆚 aggregate vs filter vs SQL

特性

aggregate

filter

自定义 SQL

用途

聚合统计

列表查询

复杂查询

聚合函数

✅ SUM/COUNT/AVG

✅ 全部

GROUP BY

✅ 原生支持

HAVING

✅ 原生支持

多表 JOIN

类型安全

✅ TypeScript

✅ TypeScript

⚠️ 需手写类型

适用场景

报表、统计、大屏

列表、搜索

复杂业务查询

⚠️ 注意事项

1. 字段类型

确保聚合字段是数值类型:

TypeScript
// ✅ 正确 - 数值字段
{ type: 'SUM', field: 'total_amount', alias: 'total' }

// ❌ 错误 - 字符串字段无法求和
{ type: 'SUM', field: 'order_no', alias: 'total' }

2. COUNT 的 field 参数

TypeScript
// 统计所有记录数
{ type: 'COUNT', field: '*', alias: 'total' }

// 统计某字段非空记录数
{ type: 'COUNT', field: 'customer_id', alias: 'customers_with_orders' }

// 统计不重复值
{ type: 'COUNT', field: 'customer_id', alias: 'unique_customers', distinct: true }

3. GROUP BY 字段顺序

多个 GROUP BY 字段时,结果按字段顺序分组:

TypeScript
// 先按年份,再按月份
groupBy: ['year', 'month']

// 结果结构:2025 → 1月, 2025 → 2月, 2024 → 12月...

4. HAVING vs WHERE

  • WHERE:聚合前过滤,减少参与聚合的数据量
  • HAVING:聚合后过滤,筛选聚合结果
TypeScript
// WHERE:先筛选已完成订单,再统计
where: { status: { $eq: 'completed' } }

// HAVING:统计所有订单,只返回销售额 > 10000 的分组
having: [{ columnName: 'total_sales', condition: { $gte: 10000 } }]

5. 性能优化

  • 使用 WHERE 提前过滤数据,减少聚合计算量
  • 合理设置 pageSize,避免返回过多分组结果
  • 对于大数据量表,建议添加索引

📚 相关文档

  • Filter API 高级过滤查询 - 列表数据查询
  • SQL API 使用指南 - 自定义 SQL 查询
  • API 使用指南 - 完整 API 概览
  • 实际应用示例 - 更多实战示例

有问题?查看 故障排查文档 或联系技术支持。

基于飞书知识库同步生成,内容以飞书源文档为准