用途
Taruvi 数据库技能是面向 Taruvi datatable 与数据库查询工作的参考模块,用于在构建或优化数据驱动界面时提供统一的查询策略。典型使用场景包括:构建由 Taruvi datatable 支撑的列表、表格或详情页;编写或优化带过滤、排序、分页的查询;构建仪表盘 KPI 卡片或汇总图表;使用 useList、useOne、useMany、useCreate、useUpdate、useDelete、useDeleteMany 等 Refine 钩子;实现 groupBy、aggregate、having 分组指标;以及对 datatable 之间的图关系进行建模。
该技能不适用于:原始存储文件查询(应使用 taruvi-storage 技能)、用户管理 CRUD(应使用 taruvi-refine-providers 技能配合 userDataProvider)、多资源操作(应使用 taruvi-functions 技能)。
主要能力
技能覆盖 Refine 钩子、查询操作符、聚合模式以及汇总视图的性能规则。核心能力包括:
- 列表/表格 UI:带分页的普通过滤行查询。
- 仪表盘卡片/KPI(单表):datatable 的 groupBy + aggregate。
- 需要来自 2 个及以上表数据的仪表盘元素:通过 appDataProvider + useCustom 使用已保存的分析查询(saved analytics query)。
- 关联数据:使用带 include/depth 元键的图(graph)选项。
- 分组指标:groupBy、aggregate、having。
技能给出了明确的偏好顺序:大多数仪表盘指标优先使用 datatable provider 的单表聚合;当仪表盘元素需要来自 2 个及以上表的数据时使用已保存的分析查询;仅当页面确实需要行数据时才使用原始行查询;绝不把完整行集拉入 React 来推导汇总指标。
使用方式
技能规定了分步操作流程:
- 打开并阅读 ../taruvi-refine-providers/references/database-provider.md,获取完整查询 API(CRUD、过滤、排序、分页、聚合、图)。
- 确认即将使用的数据操作对应的当前非弃用包路径;不要在已弃用的 provider、hook 或兼容辅助工具上引入新代码。
- 识别所需查询形态:列表/表格 UI 使用带分页的普通过滤行查询;单表仪表盘卡片/KPI 使用 datatable groupBy + aggregate;需要 2 个及以上表数据的仪表盘元素使用通过 appDataProvider + useCustom 的已保存分析查询;关联数据使用带 include/depth 元键的图选项。
- 应用偏好顺序(见上)。
- 对每个后端支撑的列表 UI:默认要求后端分页;默认列表 pageSize 为 10,建议支持 10、20、50、100 可选;搜索、过滤和排序默认必须推入后端查询;列表页默认应暴露可见的搜索输入和相关过滤控件;当列表使用 MUI DataGrid 时,默认使用 Refine useDataGrid,使分页/过滤/排序状态保持服务端驱动;除非用户明确要求客户端行为,否则不要获取行数据并在 React 中应用主列表过滤/搜索逻辑。
- 对每个网络支撑的下拉/自动补全:从后端分页查询选项(默认选项 pageSize 10);对搜索输入防抖;把搜索词推入后端过滤;避免预加载大量选项集并在客户端过滤。
- 验证查询形态可扩展,避免 N+1 模式。
技能还提供了验证清单,用于在编写查询后逐项核对,包括:单表仪表盘指标使用 datatable aggregate + groupBy;需要 2 个及以上表数据的仪表盘元素使用已保存分析查询;仪表盘/汇总视图使用一次 aggregate + groupBy 查询而非 N 次独立过滤查询;所有列表 UI 包含合理 pageSize 的分页;列表视图默认 pageSize 10 并支持 10/20/50/100;后端支撑的列表过滤、搜索、排序默认服务端化;后端支撑的列表页默认包含可见搜索和相关过滤控件;后端支撑的 MUI DataGrid 列表默认使用 useDataGrid;网络支撑的下拉/自动补全选项使用防抖的服务端搜索与分页加载;图查询有明确深度限制;having 仅在 groupBy 之后使用;无 N+1 模式;无页面为推导卡片、饼图或趋势图而拉取完整行集;无后端支撑列表页在 React 中应用主搜索/过滤逻辑(除非用户明确要求客户端行为)。
示例
带分页的过滤列表:
const { data } = useList({ resource: "orders", filters: [{ field: "status", operator: "eq", value: "pending" }], sorters: [{ field: "created_at", order: "desc" }], pagination: { pageSize: 10 }, });
列表 UI 推荐 page-size 选项:10、20、50、100(默认 10)。
生产可用的列表 UX 基线:包含可见搜索输入和常见过滤(例如状态/部门/日期);把搜索/过滤状态绑定到后端查询参数;尽可能让列表状态可 URL 同步。
单表仪表盘(datatable 聚合):
const { data } = useList({ resource: "orders", meta: { aggregate: ["count"], groupBy: ["status"], }, }); // 返回:[{ status: "pending", count: 14 }, { status: "completed", count: 82 }]
聚合后使用 having 过滤:
meta: { aggregate: ["count"], groupBy: ["team"], having: { count__gte: 5 }, }
多表仪表盘元素——已保存分析查询(当元素需要来自 2 个及以上表的数据时必需):
const { result } = useCustom({ url: "hrms-dashboard-summary", method: "post", dataProviderName: "app", payload: {}, meta: { kind: "analytics" }, });
适用场景
- 构建由 Taruvi datatable 支撑的列表、表格或详情页。
- 编写或优化带过滤、排序、分页的查询。
- 构建仪表盘 KPI 卡片或汇总图表。
- 使用 Refine 数据钩子进行 CRUD 与查询。
- 实现 groupBy、aggregate、having 分组指标。
- 对 datatable 之间的图关系建模。
限制与注意事项
技能列出了若干常见陷阱(gotchas):
- 仪表盘使用 N 次独立查询:若为每个状态/类别分别调用 useList 来构建汇总,属于性能缺陷;单表数据应替换为一次 groupBy 查询,需要 2 个及以上表数据时使用已保存分析查询。
- KPI 页面拉取完整行:若仪表盘把完整表行拉入 React 再在客户端计算总计/图表,属于缺陷;应始终把聚合推到服务端。
- 已弃用查询路径:若仪表盘仅通过已弃用包路径工作,不应作为最终实现发布;应先确定规范包 API。
- 图数据无深度限制:使用图/边查询时始终设置 depth;否则查询会遍历无界关系,在任何非平凡数据集上超时。
- having 无 groupBy:having 仅在 groupBy 之后有效,不能替代 filters 子句;单独使用 having 会静默返回空结果。
- 大数据集无分页:列表 UI 始终加分页;无界查询在超过 1000 行的表上会超时。
- 后端数据的客户端列表过滤:若列表获取后端行后在 React 中应用主搜索或过滤逻辑,属于正确性与可扩展性问题;除非用户明确要求本地过滤,应把逻辑移入后端 filters/sorters。
- 无列表控件:后端支撑的列表若没有可见搜索/过滤控件,通常不算生产可用,除非用户明确要求极简表格。
- 手动 MUI 网格状态接线:后端支撑的 MUI DataGrid 列表若用 useList 手动接线分页/过滤/排序状态,优先使用 useDataGrid,除非有具体限制必须手动接线。
- 客户端过滤远程下拉选项:若下拉一次性获取远程选项并在本地过滤,会漏掉匹配且无法扩展;应使用防抖的服务端搜索与分页选项加载。
- aggregate 需要数组:aggregate: "count" 会静默失败,应使用 aggregate: ["count"]。
- 过滤操作符拼写错误:操作符是 "eq",不是 "equals" 或 "=";常见操作符:eq、ne、lt、gt、lte、gte、contains、in。
合规规则:该技能规定的查询策略(列表的服务端搜索/过滤/排序、下拉的防抖 Autocomplete)是强制性的,不是建议;不要回退到更简单的模式;若某需求无法满足,应停止并询问用户。
参考资料
../taruvi-refine-providers/references/database-provider.md — 核心操作、查询特性、聚合模式、图。