@wubaoqi/guancopilot 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (239) hide show
  1. package/NOTICE.md +17 -0
  2. package/README.md +146 -2
  3. package/assets/coreutils.wasm +0 -0
  4. package/assets/find.wasm +0 -0
  5. package/assets/guanbi.wasm +4 -0
  6. package/assets/guancli.wasm +0 -0
  7. package/assets/guanhelm.wasm +0 -0
  8. package/assets/jq.wasm +0 -0
  9. package/assets/openskills.wasm +0 -0
  10. package/assets/rg.wasm +0 -0
  11. package/assets/sed.wasm +0 -0
  12. package/bin/guancopilot +0 -0
  13. package/bin/guanvm +0 -0
  14. package/bin/platforms.cjs +6 -0
  15. package/bin/run.cjs +39 -0
  16. package/bin/runtime.cjs +44 -0
  17. package/licenses/Go-LICENSE +27 -0
  18. package/licenses/browser-_speed-highlight_core-LICENSE +121 -0
  19. package/licenses/browser-_speed-highlight_core-package.json +14 -0
  20. package/licenses/browser-dompurify-LICENSE +202 -0
  21. package/licenses/browser-dompurify-LICENSE-MPL +373 -0
  22. package/licenses/browser-dompurify-package.json +10 -0
  23. package/licenses/browser-marked-LICENSE +44 -0
  24. package/licenses/browser-marked-package.json +10 -0
  25. package/licenses/coreutils-LICENSE +18 -0
  26. package/licenses/findutils-LICENSE +18 -0
  27. package/licenses/github.com_BurntSushi_toml_v1.6.0-COPYING +21 -0
  28. package/licenses/github.com_dustin_go-humanize_v1.0.1-LICENSE +21 -0
  29. package/licenses/github.com_google_jsonschema-go_v0.4.3-LICENSE +21 -0
  30. package/licenses/github.com_google_uuid_v1.6.0-LICENSE +27 -0
  31. package/licenses/github.com_jackc_pgpassfile_v1.0.0-LICENSE +22 -0
  32. package/licenses/github.com_jackc_pgservicefile_v0.0.0-20240606120523-5a60cdf6a761-LICENSE +22 -0
  33. package/licenses/github.com_jackc_pgx_v5_v5.11.0-LICENSE +22 -0
  34. package/licenses/github.com_jackc_puddle_v2_v2.2.2-LICENSE +22 -0
  35. package/licenses/github.com_mattn_go-isatty_v0.0.20-LICENSE +9 -0
  36. package/licenses/github.com_modelcontextprotocol_go-sdk_v1.8.0-LICENSE +216 -0
  37. package/licenses/github.com_ncruces_go-strftime_v1.0.0-LICENSE +21 -0
  38. package/licenses/github.com_remyoudompheng_bigfft_v0.0.0-20230129092748-24d4a6f8daec-LICENSE +27 -0
  39. package/licenses/github.com_santhosh-tekuri_jsonschema_v6_v6.0.3-LICENSE +175 -0
  40. package/licenses/github.com_segmentio_asm_v1.1.3-LICENSE +21 -0
  41. package/licenses/github.com_segmentio_encoding_v0.5.4-LICENSE +21 -0
  42. package/licenses/github.com_tetratelabs_wazero_v1.12.0-LICENSE +201 -0
  43. package/licenses/github.com_tetratelabs_wazero_v1.12.0-NOTICE +2 -0
  44. package/licenses/github.com_yosida95_uritemplate_v3_v3.0.2-LICENSE +25 -0
  45. package/licenses/golang.org_x_image_v0.44.0-LICENSE +27 -0
  46. package/licenses/golang.org_x_net_v0.58.0-LICENSE +27 -0
  47. package/licenses/golang.org_x_oauth2_v0.36.0-LICENSE +27 -0
  48. package/licenses/golang.org_x_sync_v0.22.0-LICENSE +27 -0
  49. package/licenses/golang.org_x_sys_v0.47.0-LICENSE +27 -0
  50. package/licenses/golang.org_x_text_v0.41.0-LICENSE +27 -0
  51. package/licenses/golang.org_x_time_v0.15.0-LICENSE +27 -0
  52. package/licenses/guanbi-skills-LICENSE +133 -0
  53. package/licenses/guanbi-skills-LICENSE.README.md +28 -0
  54. package/licenses/guanbi-skills-LICENSE.zh-CN +82 -0
  55. package/licenses/jq-COPYING +176 -0
  56. package/licenses/modernc.org_libc_v1.73.4-LICENSE +27 -0
  57. package/licenses/modernc.org_libc_v1.73.4-LICENSE-3RD-PARTY.md +305 -0
  58. package/licenses/modernc.org_mathutil_v1.7.1-LICENSE +27 -0
  59. package/licenses/modernc.org_memory_v1.11.0-LICENSE +27 -0
  60. package/licenses/modernc.org_memory_v1.11.0-LICENSE-GO +27 -0
  61. package/licenses/modernc.org_memory_v1.11.0-LICENSE-LOGO +1 -0
  62. package/licenses/modernc.org_memory_v1.11.0-LICENSE-MMAP-GO +25 -0
  63. package/licenses/modernc.org_sqlite_v1.53.0-LICENSE +26 -0
  64. package/licenses/mvdan.cc_sh_v3_v3.13.1-LICENSE +27 -0
  65. package/licenses/ripgrep-COPYING +3 -0
  66. package/licenses/ripgrep-LICENSE-MIT +21 -0
  67. package/licenses/sed-LICENSE +21 -0
  68. package/manifest.json +972 -0
  69. package/package.json +30 -4
  70. package/plugin/guancopilot.js +193 -0
  71. package/skills-bundle/.guanvm-skills-bundle +0 -0
  72. package/skills-bundle/_recipes/dashboard/gates/page_check.js +16 -0
  73. package/skills-bundle/_recipes/dashboard/gates/report_check.js +4 -0
  74. package/skills-bundle/_recipes/dashboard/knowledge/01.md +1 -0
  75. package/skills-bundle/_recipes/dashboard/knowledge/02.md +1 -0
  76. package/skills-bundle/_recipes/dashboard/knowledge/03.md +1 -0
  77. package/skills-bundle/_recipes/dashboard/knowledge/04.md +1 -0
  78. package/skills-bundle/_recipes/dashboard/knowledge/05.md +1 -0
  79. package/skills-bundle/_recipes/dashboard/knowledge/06.md +1 -0
  80. package/skills-bundle/_recipes/dashboard/template.json +41 -0
  81. package/skills-bundle/_recipes/etl/gates/etl_live_check.js +10 -0
  82. package/skills-bundle/_recipes/etl/gates/etl_report_check.js +3 -0
  83. package/skills-bundle/_recipes/etl/knowledge/01.md +1 -0
  84. package/skills-bundle/_recipes/etl/knowledge/02.md +9 -0
  85. package/skills-bundle/_recipes/etl/knowledge/03.md +1 -0
  86. package/skills-bundle/_recipes/etl/knowledge/04.md +1 -0
  87. package/skills-bundle/_recipes/etl/knowledge/05.md +1 -0
  88. package/skills-bundle/_recipes/etl/template.json +39 -0
  89. package/skills-bundle/_recipes/hints.json +46 -0
  90. package/skills-bundle/guancli/.commandface.json +155 -0
  91. package/skills-bundle/guancli/SKILL.md +342 -0
  92. package/skills-bundle/guancli/evals/evals.json +156 -0
  93. package/skills-bundle/guancli/evals/fixtures/metric-candidate-empty-search.json +13 -0
  94. package/skills-bundle/guancli/evals/fixtures/metric-candidate-prior-request.json +13 -0
  95. package/skills-bundle/guancli/evals/fixtures/metric-consumption-columns.json +46 -0
  96. package/skills-bundle/guancli/evals/fixtures/metric-consumption-metadata.json +36 -0
  97. package/skills-bundle/guancli/evals/fixtures/metric-consumption-query.json +18 -0
  98. package/skills-bundle/guancli/references/analysis-primitives.md +95 -0
  99. package/skills-bundle/guancli/references/auth-and-config.md +131 -0
  100. package/skills-bundle/guancli/references/examples/metric-date-in.json +7 -0
  101. package/skills-bundle/guancli/references/examples/metric-query-rows.py +83 -0
  102. package/skills-bundle/guancli/references/examples/metric-query.sh +6 -0
  103. package/skills-bundle/guancli/references/form-chatbi.md +199 -0
  104. package/skills-bundle/guancli/references/gateway.md +148 -0
  105. package/skills-bundle/guancli/references/metric-batch-query.md +82 -0
  106. package/skills-bundle/guancli/references/metric-commands.md +562 -0
  107. package/skills-bundle/guancli/references/metric-generic-query.md +215 -0
  108. package/skills-bundle/guancli/references/metric-json-migration.md +18 -0
  109. package/skills-bundle/guancli/references/metric-query-recipes.md +358 -0
  110. package/skills-bundle/guancli/references/preview-and-output.md +192 -0
  111. package/skills-bundle/guancli/references/resource-query.md +101 -0
  112. package/skills-bundle/guands/SKILL.md +281 -0
  113. package/skills-bundle/guands/references/calc-fields-boundaries-and-pitfalls.md +160 -0
  114. package/skills-bundle/guands/references/command-reference.md +267 -0
  115. package/skills-bundle/guands/references/incremental-and-schedule.md +157 -0
  116. package/skills-bundle/guands/references/workflows.md +256 -0
  117. package/skills-bundle/guanetl/SKILL.md +391 -0
  118. package/skills-bundle/guanetl/evals/evals.json +41 -0
  119. package/skills-bundle/guanetl/references/ETL_AI_DEVELOP.md +456 -0
  120. package/skills-bundle/guanmetric/SKILL.md +144 -0
  121. package/skills-bundle/guanmetric/evals/evals.json +117 -0
  122. package/skills-bundle/guanmetric/evals/fixtures/atomic-detail-read-model.json +18 -0
  123. package/skills-bundle/guanmetric/evals/fixtures/confirmed-template-summary.json +12 -0
  124. package/skills-bundle/guanmetric/evals/fixtures/create-result-unknown-state.json +13 -0
  125. package/skills-bundle/guanmetric/evals/forward-eval-2026-09-21.json +62 -0
  126. package/skills-bundle/guanmetric/references/metric-api-contract-examples.json +690 -0
  127. package/skills-bundle/guanmetric/references/metric-api-contract.schema.json +349 -0
  128. package/skills-bundle/guanmetric/references/metric-api-contracts.md +436 -0
  129. package/skills-bundle/guanmetric/references/metric-atomic-mutation.md +238 -0
  130. package/skills-bundle/guanmetric/references/metric-batch-status.md +71 -0
  131. package/skills-bundle/guanmetric/references/metric-business-dictionary-api-contract-examples.json +53 -0
  132. package/skills-bundle/guanmetric/references/metric-business-dictionary-api-contract.schema.json +26 -0
  133. package/skills-bundle/guanmetric/references/metric-business-dictionary.md +76 -0
  134. package/skills-bundle/guanmetric/references/metric-common-fields.md +246 -0
  135. package/skills-bundle/guanmetric/references/metric-composite-mutation.md +165 -0
  136. package/skills-bundle/guanmetric/references/metric-delete-mutation.md +70 -0
  137. package/skills-bundle/guanmetric/references/metric-derived-mutation.md +453 -0
  138. package/skills-bundle/guanmetric/references/metric-excel-template.md +365 -0
  139. package/skills-bundle/guanmetric/references/metric-expression-rules.md +146 -0
  140. package/skills-bundle/guanmetric/references/metric-flow-generate-example.json +79 -0
  141. package/skills-bundle/guanmetric/references/metric-flow-generate.schema.json +93 -0
  142. package/skills-bundle/guanmetric/references/metric-flow.md +218 -0
  143. package/skills-bundle/guanmetric/references/metric-hierarchy-api-contract-examples.json +171 -0
  144. package/skills-bundle/guanmetric/references/metric-hierarchy-api-contract.schema.json +167 -0
  145. package/skills-bundle/guanmetric/references/metric-hierarchy-api-contracts.md +193 -0
  146. package/skills-bundle/guanmetric/references/metric-mutation.md +155 -0
  147. package/skills-bundle/guanmetric/references/metric-public-dimension-api-contract-examples.json +62 -0
  148. package/skills-bundle/guanmetric/references/metric-public-dimension-api-contract.schema.json +47 -0
  149. package/skills-bundle/guanmetric/references/metric-public-dimension.md +155 -0
  150. package/skills-bundle/guanmetric/references/metric-tree-api-contract-examples.json +277 -0
  151. package/skills-bundle/guanmetric/references/metric-tree-api-contract.schema.json +263 -0
  152. package/skills-bundle/guanmetric/references/metric-tree-api-contracts.md +53 -0
  153. package/skills-bundle/guanmetric/references/metric-tree-mutation.md +500 -0
  154. package/skills-bundle/guanmetric/references/metric-validation-ownership.md +74 -0
  155. package/skills-bundle/guanvis/SKILL.md +333 -0
  156. package/skills-bundle/guanvis/evals/china_map/card_01_basic_map.js +13 -0
  157. package/skills-bundle/guanvis/evals/china_map/card_02_world_map.js +10 -0
  158. package/skills-bundle/guanvis/evals/china_map/card_03_point_map.js +12 -0
  159. package/skills-bundle/guanvis/evals/china_map/page.js +10 -0
  160. package/skills-bundle/guanvis/evals/china_map/schema.js +10 -0
  161. package/skills-bundle/guanvis/evals/comparative_mvp_roundtrip/README.md +30 -0
  162. package/skills-bundle/guanvis/evals/comparative_mvp_roundtrip/card_01_comparative_mvp.js +72 -0
  163. package/skills-bundle/guanvis/evals/comparative_mvp_roundtrip/page.js +6 -0
  164. package/skills-bundle/guanvis/evals/comparative_mvp_roundtrip/schema.js +22 -0
  165. package/skills-bundle/guanvis/evals/comparative_mvp_roundtrip/verify_default_roundtrip.sh +92 -0
  166. package/skills-bundle/guanvis/evals/complex_report_pro/card_01_monthly.js +63 -0
  167. package/skills-bundle/guanvis/evals/complex_report_pro/page.js +6 -0
  168. package/skills-bundle/guanvis/evals/complex_report_pro/schema.js +6 -0
  169. package/skills-bundle/guanvis/evals/custom_chart_echarts/card_01_bar.js +13 -0
  170. package/skills-bundle/guanvis/evals/custom_chart_echarts/card_02_pie.js +13 -0
  171. package/skills-bundle/guanvis/evals/custom_chart_echarts/charts/bar.js +11 -0
  172. package/skills-bundle/guanvis/evals/custom_chart_echarts/charts/pie.js +15 -0
  173. package/skills-bundle/guanvis/evals/custom_chart_echarts/page.js +5 -0
  174. package/skills-bundle/guanvis/evals/custom_chart_echarts/schema.js +9 -0
  175. package/skills-bundle/guanvis/evals/custom_chart_sdk/card_01_level_nodes.js +19 -0
  176. package/skills-bundle/guanvis/evals/custom_chart_sdk/charts/level_nodes.css +51 -0
  177. package/skills-bundle/guanvis/evals/custom_chart_sdk/charts/level_nodes.html +1 -0
  178. package/skills-bundle/guanvis/evals/custom_chart_sdk/charts/level_nodes.js +28 -0
  179. package/skills-bundle/guanvis/evals/custom_chart_sdk/page.js +5 -0
  180. package/skills-bundle/guanvis/evals/custom_chart_sdk/schema.js +7 -0
  181. package/skills-bundle/guanvis/evals/dynamic_fields/card_01_dynamic_dataset.js +20 -0
  182. package/skills-bundle/guanvis/evals/dynamic_fields/card_02_dynamic_metric_chart.js +16 -0
  183. package/skills-bundle/guanvis/evals/dynamic_fields/metrics.js +19 -0
  184. package/skills-bundle/guanvis/evals/dynamic_fields/page.js +9 -0
  185. package/skills-bundle/guanvis/evals/dynamic_fields/schema.js +7 -0
  186. package/skills-bundle/guanvis/evals/dynamic_fields/verify_default_roundtrip.sh +137 -0
  187. package/skills-bundle/guanvis/evals/percentage_advcalc_roundtrip/README.md +26 -0
  188. package/skills-bundle/guanvis/evals/percentage_advcalc_roundtrip/card_01_percentage_advcalc.js +44 -0
  189. package/skills-bundle/guanvis/evals/percentage_advcalc_roundtrip/card_02_scroll_percentage.js +12 -0
  190. package/skills-bundle/guanvis/evals/percentage_advcalc_roundtrip/page.js +6 -0
  191. package/skills-bundle/guanvis/evals/percentage_advcalc_roundtrip/schema.js +22 -0
  192. package/skills-bundle/guanvis/evals/rank_advcalc_roundtrip/README.md +28 -0
  193. package/skills-bundle/guanvis/evals/rank_advcalc_roundtrip/card_01_rank_advcalc.js +59 -0
  194. package/skills-bundle/guanvis/evals/rank_advcalc_roundtrip/page.js +6 -0
  195. package/skills-bundle/guanvis/evals/rank_advcalc_roundtrip/schema.js +22 -0
  196. package/skills-bundle/guanvis/evals/rank_advcalc_roundtrip/verify_default_roundtrip.sh +135 -0
  197. package/skills-bundle/guanvis/evals/running_total_advcalc_roundtrip/README.md +15 -0
  198. package/skills-bundle/guanvis/evals/running_total_advcalc_roundtrip/card_01_running_total_advcalc.js +74 -0
  199. package/skills-bundle/guanvis/evals/running_total_advcalc_roundtrip/page.js +6 -0
  200. package/skills-bundle/guanvis/evals/running_total_advcalc_roundtrip/schema.js +22 -0
  201. package/skills-bundle/guanvis/evals/sales_dashboard/card_01_revenue_column.js +10 -0
  202. package/skills-bundle/guanvis/evals/sales_dashboard/card_02_trend_line.js +9 -0
  203. package/skills-bundle/guanvis/evals/sales_dashboard/card_03_kpi.js +6 -0
  204. package/skills-bundle/guanvis/evals/sales_dashboard/card_04_pie.js +9 -0
  205. package/skills-bundle/guanvis/evals/sales_dashboard/card_05_calc_field_test.js +12 -0
  206. package/skills-bundle/guanvis/evals/sales_dashboard/page.js +11 -0
  207. package/skills-bundle/guanvis/evals/sales_dashboard/schema.js +14 -0
  208. package/skills-bundle/guanvis/evals/sales_dashboard/selector_01_region.js +10 -0
  209. package/skills-bundle/guanvis/evals/split_charts/card_01_column_split.js +10 -0
  210. package/skills-bundle/guanvis/evals/split_charts/card_02_line_split.js +10 -0
  211. package/skills-bundle/guanvis/evals/split_charts/card_03_combo_split.js +11 -0
  212. package/skills-bundle/guanvis/evals/split_charts/page.js +10 -0
  213. package/skills-bundle/guanvis/evals/split_charts/schema.js +14 -0
  214. package/skills-bundle/guanvis/evals/tab_layout/card_00_total_revenue.js +6 -0
  215. package/skills-bundle/guanvis/evals/tab_layout/card_01_revenue.js +10 -0
  216. package/skills-bundle/guanvis/evals/tab_layout/card_02_trend.js +9 -0
  217. package/skills-bundle/guanvis/evals/tab_layout/card_03_story.js +11 -0
  218. package/skills-bundle/guanvis/evals/tab_layout/page.js +23 -0
  219. package/skills-bundle/guanvis/evals/tab_layout/schema.js +11 -0
  220. package/skills-bundle/guanvis/evals/tab_layout/selector_01_region.js +8 -0
  221. package/skills-bundle/guanvis/references/api-reference.md +476 -0
  222. package/skills-bundle/guanvis/references/builder-reference.md +1676 -0
  223. package/skills-bundle/guanvis/references/chart-properties.md +2101 -0
  224. package/skills-bundle/guanvis/references/checkout-editing.md +53 -0
  225. package/skills-bundle/guanvis/references/complex-report-pro-patterns.md +398 -0
  226. package/skills-bundle/guanvis/references/dir-and-page-management.md +48 -0
  227. package/skills-bundle/guanvis/references/metric-chart-reference.md +258 -0
  228. package/skills-bundle/guanvis/references/publish-and-constraints.md +60 -0
  229. package/skills-bundle/guanvis/references/selector-reference.md +431 -0
  230. package/skills-bundle/guanvis/references/tableau-migration.md +73 -0
  231. package/skills-bundle/guanvis/references/theme.md +123 -0
  232. package/skills-bundle/guanvis/references/troubleshooting.md +25 -0
  233. package/skills-bundle/guanvis/references/validation-and-chart-patterns.md +205 -0
  234. package/skills-bundle/guanwf/SKILL.md +543 -0
  235. package/skills-bundle/guanwf/references/ETL_AI_DEVELOP.md +456 -0
  236. package/skills-bundle/guanwf/references/TASK_NODE_CONTRACTS.md +64 -0
  237. package/skills-bundle/guanwf/references/WORKFLOW_DSL.md +536 -0
  238. package/skills-bundle/guanwf/references/WORKFLOW_NODES.md +166 -0
  239. package/skills-bundle/js/SKILL.md +145 -0
@@ -0,0 +1,160 @@
1
+ # guands 计算字段、职责边界与易错点
2
+
3
+ ## 数据集计算字段
4
+
5
+ 在数据集上直接新建计算字段,无需创建 ETL。支持普通 SQL 表达式、窗口函数和聚合函数。
6
+
7
+ `--calc-type` 选项:
8
+ - `normal`(默认): 行级表达式,如 `[利润]/[销售额]`
9
+ - `window`: 窗口函数,如 `SUM([x]) OVER(PARTITION BY [y] ORDER BY [z])`
10
+ - `aggregation`: 聚合函数,如 `SUM([利润])/SUM([销售额])`,结果在卡片中按维度聚合
11
+
12
+ ```bash
13
+ # 新建计算字段
14
+ guands dataset calc-field add <dsId> --name "利润率" --formula "[利润]/[销售额]"
15
+ guands dataset calc-field add <dsId> --name "发货天数" --formula "datediff([发货日期], [订单日期])" --type INT
16
+ guands dataset calc-field add <dsId> --name "状态" --formula "CASE WHEN [利润] > 0 THEN '盈利' ELSE '亏损' END" --type STRING
17
+ guands dataset calc-field add <dsId> --name "利润率_聚合" --formula "SUM([利润])/SUM([销售额])" --calc-type aggregation
18
+
19
+ # 更新计算字段
20
+ guands dataset calc-field update <dsId> --fd-id <fdId> --formula "[利润]/[销售额]*100"
21
+ guands dataset calc-field update <dsId> --fd-id <fdId> --name "新利润率" --formula "[利润]/[销售额]"
22
+
23
+ # 删除计算字段
24
+ guands dataset calc-field delete <dsId> --fd-id <fdId> --yes
25
+ ```
26
+
27
+ **批量新建计算字段**(N 个字段用一次命令,不要循环调用 add):
28
+
29
+ ```bash
30
+ # vcs.json 是 JSON 数组,每条含 name/formula 必填,alias/fdType/calculationType/annotation 可选
31
+ guands dataset calc-field batch-add <dsId> --file vcs.json --dry-run # 先预检
32
+ guands dataset calc-field batch-add <dsId> --file vcs.json
33
+ # 中途失败后修正文件并幂等重跑(已创建成功的同名字段自动跳过)
34
+ guands dataset calc-field batch-add <dsId> --file vcs.json --skip-existing
35
+ ```
36
+
37
+ batch-add 特性:
38
+ - 提交前本地预检:批内/与现有字段的展示名冲突、保留字符、公式 `[字段引用]` 完整性
39
+ - 批内字段互相引用时自动按依赖拓扑排序创建(如"利润率分档"引用"利润率"),循环引用报错
40
+ - 逐条提交(后端无批量端点),失败默认继续并汇总记账,`--fail-fast` 首错即停;依赖失败字段的条目自动级联跳过
41
+ - 输入兼容 `guancli ds get <srcDsId> --raw` 输出的字段对象原样内容(fdId/dsId 等自动忽略),
42
+ 跨数据集/跨环境克隆计算字段(计算字段分布在 `columns` 与 `virtualColumns` 中,按 formula 非空过滤):
43
+ `guancli ds get <srcDsId> --raw | jq '[(.data.columns[]?, .data.virtualColumns[]?) | select(.formula != null and .formula != "")]' > vcs.json`
44
+
45
+ **对齐已有字段用 `calc-field apply`**(不存在则建,已存在且一致则跳过,不一致默认整批中断并逐项列出
46
+ `formula`/`fdType`/`alias`/`annotation` 线上与本次的取值)。文件里没写 `fdType` 时 apply **不断言类型**
47
+ (新建仍按 DOUBLE 建):COUNT 一类在线上是 LONG 的字段不会因为文件缺省而被判成"不一致"。
48
+
49
+ **公式语法**:
50
+ - 抽取/上传数据集 → Apache Spark SQL 语法
51
+ - 直连数据集 → 目标数据库 SQL 语法
52
+ - 公式中用 `[字段名]` 方括号引用字段(中文、特殊字符均需方括号转义)
53
+
54
+ **分组字段(把维度取值归类分档)用 CASE WHEN 计算字段实现**:
55
+
56
+ BI UI 的「新建分组字段」本质是后端把分组配置翻译成 CASE 表达式执行,用 calc-field 直接写
57
+ CASE WHEN 公式等价且更可控。不提供单独的分组字段命令。自然语言 → 公式对照:
58
+
59
+ ```bash
60
+ # "把省份按华东/华南分组,其余归为其他"(项目分组)
61
+ guands dataset calc-field add <dsId> --name "区域分组" --type STRING \
62
+ --formula "CASE WHEN [省份] IN ('上海','江苏','浙江') THEN '华东' WHEN [省份] IN ('广东','广西') THEN '华南' ELSE '其他' END"
63
+
64
+ # "金额大于1000算高,其余算低"(条件分组)
65
+ guands dataset calc-field add <dsId> --name "金额分档" --type STRING \
66
+ --formula "CASE WHEN [金额] > 1000 THEN '高' ELSE '低' END"
67
+
68
+ # "金额每100一档"(固定步长分组)
69
+ guands dataset calc-field add <dsId> --name "金额区间" --type STRING \
70
+ --formula "CONCAT(FLOOR([金额]/100)*100, '-', FLOOR([金额]/100)*100+100)"
71
+
72
+ # "未分组的值各自独立显示"(不合并为"其他")→ ELSE 返回源字段
73
+ # ... ELSE [省份] END
74
+ ```
75
+
76
+ 注意事项:
77
+ - 写 IN 列表前先用 `guancli ds preview <dsId>` 或 `guancli ds execute-sql --inputs <dsId> --sql "SELECT DISTINCT \`<字段>\` FROM \`<数据集名>\`"` 确认字段实际取值,避免拼错枚举值
78
+ - 多个分组字段一起建时用 `calc-field batch-add`
79
+ - BI UI 里通过可视化编辑器创建的分组字段,在 `dataset fields` 输出的来源列显示为「分组列」;
80
+ 这类字段 CLI 无法原地修改分组配置(只能 UI 改,或用 CASE WHEN 计算字段重建后删除原字段)
81
+
82
+ **何时用数据集计算字段 vs 卡片级 calcField vs ETL**:
83
+
84
+ | 场景 | 推荐方式 | 原因 |
85
+ |---|---|---|
86
+ | 行级计算(如 `[利润]/[销售额]`) | **数据集计算字段**(`--calc-type normal`) | 所有卡片和筛选器都能引用 |
87
+ | 需要在筛选器中引用的计算字段 | **数据集计算字段** | selector 只能绑定数据集物理字段 |
88
+ | 聚合计算(如 `SUM([利润])/SUM([销售额])`) | **数据集计算字段**(`--calc-type aggregation`) | 所有卡片都能引用,按维度自动聚合 |
89
+ | 维度取值分组/分档(区域分组、金额分档) | **数据集计算字段**(CASE WHEN,见上节) | 等价于 UI 分组字段且 CLI 可控 |
90
+ | 窗口函数(如 `SUM([x]) OVER(PARTITION BY [y])`) | **数据集计算字段**(`--calc-type window`) | 数据集级别支持窗口函数 |
91
+ | 多表 JOIN + 复杂转换 | **ETL**(guanetl) | 需要先合表再计算 |
92
+ | 只为单个图表临时使用的公式 | **卡片级 calcField** | 不污染数据集 |
93
+
94
+ ## 数据集影响分析
95
+
96
+ ```bash
97
+ # 查看数据集被哪些卡片使用
98
+ guands dataset cards <ds_id>
99
+
100
+ # 查看数据集字段详情(含物理字段和计算字段)
101
+ guands dataset fields <ds_id>
102
+ ```
103
+
104
+ ## 与 guancli 的职责边界(选择决策树)
105
+
106
+ **核心原则**:guancli = 只读分析,guands = 写操作 + 数据集管理。两者共享认证配置。
107
+
108
+ | 你要做什么? | 用哪个工具 | 命令 |
109
+ |---|---|---|
110
+ | 查看数据集目录树 | guancli | `guancli ds tree` |
111
+ | 搜索数据集 | guands | `guands dataset list <关键词>` |
112
+ | 查看数据集详情+血缘+上下游 | guancli | `guancli ds get <dsId>` |
113
+ | 查看数据集字段列表(含计算字段) | guands | `guands dataset fields <dsId>` |
114
+ | 预览数据集数据 | guancli | `guancli ds preview <dsId>` |
115
+ | 创建数据集 | guands | `guands dataset create-db/create-query/import` |
116
+ | 刷新数据集 | guands | `guands dataset refresh <dsId>` |
117
+ | 配置增量/定时更新 | guands | `guands dataset update-setting/schedule` |
118
+ | 设置/清空去重主键 | guands | `guands dataset primary-key set/clear` |
119
+ | 新建/更新/删除计算字段 | guands | `guands dataset calc-field add/update/delete` |
120
+ | 批量新建计算字段 | guands | `guands dataset calc-field batch-add <dsId> --file vcs.json` |
121
+ | 重命名/移动/删除数据集 | guands | `guands dataset rename/move/delete` |
122
+ | 替换/追加数据集数据 | guands | `guands dataset replace-data / append-data` |
123
+ | 清理数据集数据 | guands | `guands dataset clear-data <dsId> --where/--all` |
124
+ | 查看数据集行列权限 | guands | `guands dataset permission get <dsId>` |
125
+ | 查看数据集被哪些卡片使用 | guands | `guands dataset cards <dsId>` |
126
+ | 查看 ETL 详情/血缘 | guancli | `guancli etl get <etlId>` |
127
+ | 查看页面详情/卡片列表 | guancli | `guancli page get <pgId>` |
128
+ | 管理连接器/账号 | guands | `guands connector/account` |
129
+ | 管理目录 | guands | `guands dir` |
130
+
131
+ **简记**:需要"改"数据集的任何属性 → guands;只需要"看"信息或分析血缘 → guancli
132
+
133
+ ## AI 使用易错点
134
+
135
+ 以下是 AI 调用此工具时容易犯的错误,请特别注意:
136
+
137
+ 1. **密码必须 Base64 编码**:`wrapAuthConfig` 已自动处理,但如果直接构造 `--config` JSON,`password` 字段需要是 Base64 编码后的值
138
+ 2. **异步 API 必须轮询**:`account tables`、`account preview`、`dataset create-db/create-query` 中的预览步骤都是异步的,CLI 会在进程内部轮询到 `FINISHED` 再继续,任务 ID 不对外暴露
139
+ 3. **创建数据集必须先获取列信息**:不能跳过预览步骤直接创建,后端要求 `columns` 字段非空
140
+ 4. **`sourceType` 枚举值**:抽取用 `GUAN_INDEX`(不是 `GUANINDEX`),直连用 `DIRECT_CONNECT_DATABASE`
141
+ 5. **抽取模式必须包含 `priority`**:默认 `"MEDIUM"`,否则 BI 界面显示为空
142
+ 6. **`cron` 字段必填**:即使不启用定时更新,也需要传递默认的 `cron` 配置
143
+ 7. **SQL 中的表名引用**:PostgreSQL 表名需要双引号包裹(如 `"link_data_source"`),优先使用 `fetchTableSQLMap` 获取服务端生成的 SQL
144
+ 8. **API 方法区分**:`get-table-list-async` 和 `get-schema-list` 是 **GET** 请求,`batch-preview-table-data-async` 和 `preview-table-data-async` 是 **POST** 请求
145
+ 9. **删除 API 路径特殊**:账号删除是 `/api/oridel/account/{id}`,数据集删除是 `/api/oridel/data-source/{id}`(不是 `/api/account/{id}/delete`);数据集批量移动是 `/api/data-source/move`(没有 `/batch-move` 路由,单个移动才是 `/api/data-source/{dsId}/move`)
146
+ 10. **增量 SQL 必须使用时间宏**:不要使用 `CURDATE()`、`NOW()`、`CURRENT_DATE` 等数据库函数,应使用 BI 时间宏如 `{{{today}}}`、`{{{yesterday}}}`、`{{{today - 7 days}}}`。时间宏语法是三花括号 `{{{ expression }}}`,不是 `${参数名}`
147
+ 11. **`account preview` 服务端截断为 30 行**:`preview-table-data-async` API 的行数限制由后端域级配置 `datasourcePreviewLineLimit` 控制,默认 30 行。客户端无法传递 limit 参数覆盖此值,即使 SQL 中写了更大的 LIMIT 也会被服务端截断。如果输出恰好 30 行,CLI 会打印截断警告。需要全量数据时应使用 `guands dataset` 相关命令或 `guancli ds preview` 代替
148
+ 11. **update-setting 会读取现有配置**:`dataset update-setting` 会先 GET 当前数据集配置,保留现有 cron 等设置,只更新增量相关字段
149
+ 12. **refresh --wait 有超时**:默认 300 秒,大数据集全量更新可能需要更长时间,用 `--timeout 600` 增加;若原 task 失败后发现后续 task,继续等待仍共享这一个总超时预算
150
+ 13. **不要对同一数据集并行触发多个 refresh**:`dataset refresh` 会先检查数据集状态,已有更新时普通调用不重复提交,`--wait` 会加入已有任务。需要并行刷新多个数据集时,按数据集分别执行 `dataset refresh <dsId> --wait`(可并行起多个进程),结论以各数据集自身状态为准
151
+ 14. **定时更新频率限制**:`dataset schedule` 最高支持 5 分钟一次,低于 1 小时间隔会输出性能警告。建议 ODS 增量至少每小时,避免对数据库造成过大压力
152
+ 15. **不提供取消任务能力**:CLI 没有按任务 ID 取消任务的命令;需要停止正在执行的刷新时请到 BI 管理中心任务详情操作
153
+ 16. **create-db/create-query 抽取模式会自动触发首次抽数**:建集成功后 BI 服务端自动入队一次全量抽数(`dataset get` 显示 UPDATING/WAITING、rowCount=0 属正常加载中)。不要写"建完统一 refresh"的脚本;CLI 虽会识别已有任务并避免重复提交,但正确姿势仍是建集后用 `dataset refresh <dsId> --wait` 加入已有抽数,或轮询 `dataset get <dsId>` 等状态变 FINISHED。只有自动抽数明确 FAILED 且没有后续成功任务时才重跑
154
+ 17. **大批量抽数失败先查并行争抢,别急着怪单表太大**:BI 侧存在多道约 30 分钟级别的硬超时(任务最大运行时长 / Spark 单 job 超时 / 数据库连接 Socket timeout,具体阈值以目标环境管理中心配置为准),且「数据库数据集更新失败重试」默认未启用。批量建/刷几十张大表时,多任务争抢数据库连接池与集群资源,单表耗时可能远超串行基准(串行参考:200 万行/40 列 ≈ 2 分钟,1000 万行/40 列 ≈ 10 分钟),被拖过超时即 FAILED 且不会自动重试。诊断与应对:
155
+ - `create-db --wait` 会逐表报出首抽 FAILED 及原因摘要;深层堆栈需在 BI 管理中心任务详情查看
156
+ - 大表分批创建/刷新(每批 5~10 张,用 `create-db --wait` 等上一批首抽完成再提交下一批),避免同时全量入队
157
+ - 零散 FAILED 的表等高峰过后单独 `dataset refresh <dsId> --wait` 重跑即可,通常能成功
158
+ - 长期方案:请 BI 管理员在管理中心启用「数据库数据集更新支持失败重试」并评估调大超时阈值
159
+ 18. **填报表单不会自动暴露成数据集**:表单(fmId)与数据集(dsId)是两类实体,`dataset list` 搜不到表单。要让表单数据进下游 ETL,先用 `guands dataset create-form <fmId>` 创建 GUAN_FORM 填报数据集(fmId 用 `guancli form list` 查)。数据集 live-linked 到表单:表单新增数据后需 `dataset refresh` 或配置 `dataset schedule` 定时同步。要求环境已开通表单填报功能(未开通时表单接口返回 423)
160
+ 19. **`--dir-id` 只接受数据集(DATA_SET)目录树中的目录 ID**:BI 中页面/ETL/工作流等各资源有独立目录树,目录 ID 互不通用。有效 ID 一律以 `guands dir tree` 输出为准。注意读写行为不对称:`dataset list --dir-id <无效ID>` 静默返回空列表(不报错),而 move/import/create-db 等写操作会失败(服务端报 1002/1012「数据集存储目录不存在」)。CLI 已在写操作前做目录预校验并给出具体原因,勿以 `list` 不报错推断目录 ID 有效
@@ -0,0 +1,267 @@
1
+ # guands 常用命令参考
2
+
3
+ ## 常用命令
4
+
5
+ ### 连接器(Connector)
6
+
7
+ ```bash
8
+ guands connector list # 列出所有连接器
9
+ guands connector get <cn_id> # 连接器详情
10
+ ```
11
+
12
+ ### 连接账号(Account)
13
+
14
+ ```bash
15
+ guands account list # 列出所有账号
16
+ guands account list 关键词 # 搜索账号
17
+ guands account get <ac_id> # 账号配置详情
18
+ guands account schemas <ac_id> # 列出 Schema
19
+ guands account tables <ac_id> # 列出表
20
+ guands account tables <ac_id> --schema public # 指定 Schema 列出表
21
+ guands account columns <ac_id> --table users # 查看表的列信息(schema 缺省取账号配置的 schema/database)
22
+ guands account columns <ac_id> --table users --schema sales # 显式指定 Schema
23
+ guands account test <cn_id> --config '{"host":"localhost","port":5432,...}'
24
+ guands account create <cn_id> --config '{"name":"生产库","host":"db.example.com",...}'
25
+ guands account rename <ac_id> --name "新名称" # 原地改名,保留 acId、凭证、权限和数据集引用
26
+ guands account update <ac_id> --host 10.0.0.8 --password 'secret' --dry-run # 预览连接配置更新计划
27
+ guands account update <ac_id> --host 10.0.0.8 --password 'secret' # 原地更新连接配置
28
+ guands account update <ac_id> --config '{"port":"3307","password":"secret"}' # 字段级增量 JSON
29
+ guands account preview <ac_id> --table users # 预览表数据(默认最多 30 行)
30
+ guands account preview <ac_id> --sql "SELECT * FROM orders LIMIT 10" # SQL 查询预览
31
+ guands account refresh <ac_id> # 刷新元数据缓存
32
+ guands account delete <ac_id> --yes # 删除账号
33
+ ```
34
+
35
+ `account rename` 会先确认账号存在,调用后端名称更新接口后再回读校验;相同名称为 no-op。
36
+ 命令不会删除或重建账号,底层不支持、权限不足或回读不一致时直接失败。
37
+
38
+ `account update` 原地更新连接配置(host/端口/库名/用户/密码/schema),保留 acId、权限和数据集引用:
39
+
40
+ - 只需提供要修改的字段,其余从线上现状合并;`--config` 是字段级增量 JSON,不是全量覆盖。
41
+ - **密码等敏感字段后端不回读**:字段在当前连接模式下激活且必填时(常规数据库账号的 password 即是),修改配置必须重新提供 `--password`(与 BI 编辑账户行为一致);密码托管等条件模式下不生效的字段无需提供,显式传入会被拒绝,避免持久化无效值。
42
+ - 所有显式提供的字段必须属于该连接器的表单字段且在当前配置下生效,否则报错(拦截拼写错误和不生效的模式字段)。
43
+ - 默认先做连接测试,失败则不做任何修改;`--skip-test` 可跳过,服务端落库前仍会再认证一次,认证失败账号保持原状。
44
+ - 仅支持基础数据库类连接器(MySQL/PostgreSQL/Oracle/SQL Server/ClickHouse 等标准 host/port 表单);
45
+ MongoDB、SAP、FTP、服务器文件、对象存储等特殊连接器不支持,jdbcUrl 含 `${...}` 占位符的账号不支持。
46
+ - 仅账号所有者可执行;改所有者、换连接器类型(cnId)不支持。仅改名用 `account rename`。
47
+ - 先 `--dry-run` 查看合并后的请求计划(敏感字段脱敏显示),确认后再真实执行。
48
+
49
+ ### 数据集(DataSource)
50
+
51
+ > **注意**:`dataset list` / `dataset get` 返回的行数(rowCount)是后端记录的元数据快照,不会在每次查询时实时计算,refresh 后也不一定立即更新。该值仅供参考,不应作为数据完整性校验的依据。
52
+ >
53
+ > **`dataset list --dir-id <dirId>` 为「子树递归」语义**:返回该目录**及其所有子目录**下的全部数据集,而非仅直属一层。底部「共 N 个数据集」是该范围的命中总数(默认只显示前 50 条,用 `--offset` / `--limit` 翻页)。需要程序化解析时用 `-f json`(输出统一字段的 JSON 数组)。
54
+
55
+ ```bash
56
+ guands dataset list # 列出数据集
57
+ guands dataset list 销售 # 按名称搜索
58
+ guands dataset list --type DIRECT_CONNECT # 按类型筛选
59
+ guands dataset list --ac-id <acId> # 按账号筛选
60
+ guands dataset list --dir-id <dirId> # 按目录筛选(含所有子目录,递归)
61
+ guands dataset get <ds_id> # 数据集详情(含字段)
62
+ guands dataset fields <ds_id> # 字段列表(含计算字段和敏感标记)
63
+ guands dataset cards <ds_id> # 使用该数据集的卡片
64
+ guands dataset refresh <ds_id> # 触发更新(立即返回,"添加新数据"模式)
65
+ guands dataset refresh <ds_id> --wait # 触发更新并等待完成
66
+ guands dataset refresh <ds_id> --wait --timeout 600 # 最多等10分钟
67
+ guands dataset refresh <ds_id> --overwrite --wait # "覆盖旧数据"模式(全量覆盖,忽略增量配置)
68
+ # WebService(API) 数据集(displayType=WEB_SERVICE)暂不支持 refresh/schedule/update-setting/sync-schema/save-as,
69
+ # CLI 读到该类型会直接拒绝且不提交请求,只能在 BI 网页端操作
70
+ guands dataset update-setting <ds_id> --incremental --incremental-sql "SELECT * FROM t WHERE dt >= '{{{today - 7 days}}}'" --preclean --preclean-rule "dt >= '{{{today - 7 days}}}'" # 配置增量(先删后插)
71
+ guands dataset update-setting <ds_id> --incremental --incremental-sql "SELECT * FROM t WHERE dt >= '{{{yesterday}}}'" # 配置增量 SQL
72
+ guands dataset primary-key set <ds_id> --columns "id" # 设置/替换去重主键(异步任务,默认等待并回读验证)
73
+ guands dataset primary-key set <ds_id> --columns "tenant_id,id" --dry-run # 预览复合主键修改请求
74
+ guands dataset primary-key clear <ds_id> # 清空去重主键(异步任务,默认等待并回读验证)
75
+ guands dataset update-setting <ds_id> --incremental=false # 关闭增量
76
+ guands dataset update-setting <ds_id> --auto-sync-schema on # 开启"自动更新数据结构"(更新时源端新增列自动带入;缺列结构不变;抽取需配合增量启用,直连直接生效)
77
+ guands dataset sync-schema plan <ds_id> # 按源端最新结构生成 schema 同步计划(数据库或 GUAN_FORM;加列/删列/改名/改类型)
78
+ guands dataset sync-schema plan <ds_id> --sql "SELECT ..." # SQL 数据集同时改查询语句
79
+ guands dataset sync-schema apply <ds_id> --plan plan.json --mode schema-only # 提交同步(仅更新结构,不覆写数据)
80
+ guands dataset sync-schema apply <ds_id> --plan plan.json --mode reset # 提交同步并重置数据集(全量覆写;直连只能用此模式)
81
+ guands dataset rename <ds_id> --name "新名称"
82
+ guands dataset alias <ds_id> --fd-id <fd_id> --alias "展示名" # 单字段改展示名
83
+ guands dataset update-fields <ds_id> --alias <fd_id>=用户名 --annotation <fd_id>=注释 # 批量改展示名/注释(可重复;空值=清除)
84
+ guands dataset update-fields <ds_id> --file updates.json # 批量文件模式: [{"fdId":...,"alias":...,"annotation":...}],字段中文化推荐
85
+ # 展示名规则(CLI 已做写前预校验): 不能含保留字符 [ ] ` ( ) { }(全角()〔〕可用);
86
+ # 展示名在数据集内必须唯一,且不能与其他字段的原始名相同(后端 2002 duplicateFieldError)
87
+ guands dataset move <ds_id> --dir-id <dir_id>
88
+ guands dataset save-as <ds_id> --name "副本" --dir-id <dir_id> # --dir-id 缺省=保存到源数据集所在目录
89
+ guands dataset delete <ds_id> --yes
90
+ guands dataset batch-move --ids "ds1,ds2" --dir-id <dir_id>
91
+ guands dataset batch-delete --ids "ds1,ds2" --yes
92
+ guands dataset create-db --ac-id <acId> --tables "t1,t2" --dir-id <dirId> # 从表名批量创建抽取数据集
93
+ # 表 SQL 一律取自服务端按数据源方言生成的结果(MySQL 反引号 / PG 双引号);账号表列表拉取失败时整批不创建,
94
+ # 单张表名不在列表中(大小写、schema 前缀不一致)时跳过该表并计入失败,可先用 account tables <acId> 核对或改用 create-query
95
+ guands dataset create-db --ac-id <acId> --tables "t1" --ds-names "用户表" --dir-id <dirId> # 指定数据集显示名称
96
+ guands dataset create-db --ac-id <acId> --tables "t1" --mode direct --dir-id <dirId> # 从 DB 创建直连数据集
97
+ guands dataset create-db --ac-id <acId> --tables "t1" --mode direct --realtime=false --dir-id <dirId> # 直连但禁用实时卡片缓存
98
+ guands dataset create-db --ac-id <acId> --tables "t1" --mode direct --cache-interval 300 --dir-id <dirId> # 直连,缓存 5 分钟
99
+ guands dataset create-db --ac-id <acId> --tables "orders" --incremental --incremental-sql "SELECT * FROM orders WHERE data_date >= '{{{today - 7 days}}}'" --preclean --preclean-rule "data_date >= '{{{today - 7 days}}}'" --dir-id <dirId> # 创建时直接配置增量
100
+ guands dataset create-db --ac-id <acId> --tables "users" --incremental --incremental-sql "SELECT * FROM users WHERE update_time >= '{{{yesterday}}}'" --primary-keys "id" --dir-id <dirId> # 创建时配置主键去重
101
+ guands dataset create-query --ac-id <acId> --name "自定义查询" --sql "SELECT u.id, o.amount FROM users u JOIN orders o ON u.id = o.uid" --dir-id <dirId> # 从 SQL 创建
102
+ guands dataset create-query --ac-id <acId> --name "直连查询" --sql "SELECT * FROM orders" --mode direct --dir-id <dirId> # SQL 直连
103
+ guands dataset create-form <fmId> --dir-id <dirId> # 从填报表单创建填报数据集(fmId 用 guancli form list 查)
104
+ guands dataset create-form <fmId1> <fmId2> --ds-names "表A,表B" --dir-id <dirId> # 批量,显示名一一对应
105
+ guands dataset import /tmp/data.csv --dir-id <dirId> # 从 CSV 创建数据集
106
+ guands dataset import /tmp/report.xlsx --sheet "销售明细" --preview --dir-id <dirId> # 多 Sheet Excel 必须指定一个 Sheet
107
+ guands dataset import /tmp/report.xlsx --sheet "销售明细" --header-row 3 --dir-id <dirId> # Excel 表头在第 3 行
108
+ guands dataset import /tmp/data.csv --encoding GB18030 --delimiter ";" --dir-id <dirId> # 显式指定 CSV 编码/分隔符
109
+ guands dataset import /tmp/large.xlsx --sheet "数据" --timeout 900 --dir-id <dirId> # 默认等待导入任务完成,大文件可延长超时
110
+ guands dataset replace-data <dsId> /tmp/fixed.csv # 不带 --yes:只打印执行计划(对象/行数/风险),非零退出
111
+ guands dataset replace-data <dsId> /tmp/fixed.csv --yes # 用户确认后:替换现有数据集数据(保留 dsId)
112
+ guands dataset replace-data <dsId> /tmp/report.xlsx --sheet "销售明细" --yes # 多 Sheet Excel 必须指定一个 Sheet
113
+ guands dataset append-data <dsId> /tmp/new_rows.csv --yes # 追加数据(保留已有数据)
114
+ guands dataset append-data <dsId> /tmp/report.xlsx --sheet "销售明细" --yes # 多 Sheet Excel 必须指定一个 Sheet
115
+ guands dataset append-data <dsId> /tmp/daily.csv --distinct-by "订单ID" --yes # 追加并按主键去重
116
+ guands dataset clear-data <dsId> --where "日期 < 2024-01-01" --yes # 按条件清理数据(危险操作,默认只预览)
117
+ guands dataset clear-data <dsId> --all --yes # 清空全部数据(保留结构与 dsId)
118
+ guands dataset permission get <dsId> # 查看行列权限(只读,含模板内容)
119
+ ```
120
+
121
+ `sync-schema apply` 的 `--mode` 必填;GUAN_FORM 优先使用 `schema-only`,只有用户明确授权全量覆写时才可用 `reset`。提交后 CLI 严格回读最终物理字段集合、字段类型、数据集状态,并分别校验 matched、remapped、confirmedDrops、added;任一不一致都返回非零。后置验收失败不代表远端一定未生效,禁止直接重试旧 plan,应先执行 `dataset fields <dsId>` 回读,再重新生成 plan。`rowCount` 是延迟快照,不参与该门禁。
122
+
123
+ `dataset refresh` 会先读取数据集 `status` 和当前任务信息。状态为
124
+ `WAITING/PROCESSING/UPDATING` 时,普通 refresh 返回成功但不重复提交;`--wait`
125
+ 改为等待已有任务。`CREATING/CLEARING/CHANGING_KEYS/CHANGE_SCHEMA` 等其他互斥操作
126
+ 只会阻止提交并返回明确冲突,不会被当成已有 refresh 成功。`--raw`
127
+ 在此 no-op 场景输出带 `submitted:false`、`reason:already_updating` 的本地 JSON,
128
+ 用于让脚本区分“已提交”和“已有更新,无需重复提交”。`--overwrite` 不会静默加入
129
+ 现有任务,因为无法证明现有任务也是覆盖更新,会明确报冲突并要求稍后重试;已提交的
130
+ 覆盖更新如果失败,也不会用另一个普通任务的成功替代。
131
+
132
+ 若本次更新任务 `FAILED/CANCELED`,同一数据集仍可能被另一个任务更新成功;
133
+ `dataset refresh --wait` 会在能证明存在后续更新任务时继续等待或按数据集最新
134
+ `FINISHED` 收敛。CLI 不提供按任务 ID 查询、等待或取消任务的命令:等待一律以
135
+ dsId 为入口(`refresh --wait`、`create-db --wait`),当前状态用 `dataset get <dsId>` 查看。
136
+
137
+ `dataset import` 每次只接受一个文件并且最多创建一个数据集。Excel 单 Sheet 自动选择;
138
+ 多 Sheet 文件必须用 `--sheet <名称>` 指定一个,名称由 BI 上传接口解析并返回,CLI
139
+ 不在本地解析 Excel。该命令与普通异步创建命令不同:它默认等待
140
+ `/api/import/batch-import` 触发的导入到终态。任务只有 `FINISHED` 才返回 0;
141
+ `FAILED/CANCELED`、等待超时、同步创建失败或响应缺少任务标识都返回非零。
142
+ 命令不会自动删除失败数据集。上传前还会检查 `.csv` 文件内容,若实际是
143
+ XLSX/ZIP/OLE 容器会直接拒绝,避免服务端先创建乱码数据集再异步失败。
144
+
145
+ `append-data` 对应 BI UI 的「追加数据」:已有数据保留,新数据追加进去;
146
+ `--distinct-by "列a,列b"` 按指定物理列去重(重复时保留新数据,即 upsert 语义),
147
+ 适合周期性补数。追加前自动校验文件列名与数据集一致,追加后报告行数增量。
148
+ 支持 `--dry-run` 先看执行计划。`append-data` 和 `replace-data` 均不会隐式合并
149
+ Excel Sheet:单 Sheet 自动选择,多 Sheet 必须通过 `--sheet <名称>` 指定一个;
150
+ Sheet 名称在真实执行时由 BI 上传接口解析并校验,CLI 不在本地解析 Excel。
151
+
152
+ ### 清理数据(clear-data,危险操作)
153
+
154
+ ```bash
155
+ guands dataset clear-data <dsId> --where "日期 < 2024-01-01" # 先预览(默认不执行)
156
+ guands dataset clear-data <dsId> --where "日期 < 2024-01-01" --yes # 确认清理
157
+ guands dataset clear-data <dsId> --where "区域 in 华东,华南" --where "金额 > 1000" --yes # 多条件 AND
158
+ guands dataset clear-data <dsId> --all --dry-run # 只看全量清空会删掉什么
159
+ guands dataset clear-data <dsId> --all --yes # 清空全部数据(结构与 dsId 保留)
160
+ ```
161
+
162
+ 对应 BI UI 的「数据清理」,被清理的数据不可恢复。安全设计:
163
+
164
+ - 必须显式二选一:`--where`(按条件)或 `--all`(清空全部)
165
+ - 默认只调 preview-on-clear 展示待清理数据样本,追加 `--yes` 才真正执行
166
+ - `--where` 格式 `"字段 操作符 值"`,操作符支持 `= != > >= < <= in not-in contains not-contains between is-null not-null`;`in`/`not-in` 值逗号分隔,`between` 是 `"起,止"`,`is-null`/`not-null` 不带值;字段可用名称或别名
167
+ - 仅支持抽取(GUAN_INDEX)/API/文件上传类型数据集;直连不支持;数据集正在刷新时后端拒绝清理
168
+ - 执行后回读行数,报告 `清理前 → 清理后(清理 N 行)`
169
+
170
+ ### 行列权限(permission,只读)
171
+
172
+ ```bash
173
+ guands dataset permission get <dsId> # 查看行/列权限配置(含关联模板内容)
174
+ ```
175
+
176
+ 展示列权限(禁用列/可见列)、行权限(条件规则/自定义表达式 + 默认规则)、
177
+ 是否对所有者生效,以及每条规则适用的用户/用户组。
178
+ 若数据集关联了行列权限模板(BI「行列权限模板」功能),实际生效的是模板规则,
179
+ 命令会自动读取并展示模板名称与模板内的规则内容。
180
+ 设置/修改行列权限暂不支持 CLI,请走 BI 网页端(数据集 → 行列权限)。
181
+
182
+ ### 计算字段(Calc Field)
183
+
184
+ ```bash
185
+ guands dataset calc-field add <ds_id> --name "利润率" --formula "[利润]/[销售额]"
186
+ guands dataset calc-field add <ds_id> --name "天数" --formula "datediff([发货日期], [订单日期])" --type INT
187
+ guands dataset calc-field add <ds_id> --name "利润率_聚合" --formula "SUM([利润])/SUM([销售额])" --calc-type aggregation
188
+ guands dataset calc-field update <ds_id> --fd-id <fd_id> --formula "[利润]/[销售额]*100"
189
+ guands dataset calc-field delete <ds_id> --fd-id <fd_id> --yes
190
+ guands dataset calc-field batch-add <ds_id> --file vcs.json # 批量新建(N 个字段不要循环调 add)
191
+ ```
192
+
193
+ ### 定时更新(Schedule)
194
+
195
+ ```bash
196
+ guands dataset schedule <ds_id> --cron-type daily --hour 2 --minute 0 # 每天 02:00
197
+ guands dataset schedule <ds_id> --cron-type hourly --interval 4 # 每 4 小时
198
+ guands dataset schedule <ds_id> --cron-type minute --interval 30 # 每 30 分钟
199
+ guands dataset schedule <ds_id> --cron-type weekly --day-of-week MON --hour 6 # 每周一 06:00
200
+ guands dataset schedule <ds_id> --cron-type monthly --day-of-month 1 --hour 3 # 每月 1 号 03:00
201
+ guands dataset schedule <ds_id> --disable # 关闭定时更新
202
+ ```
203
+
204
+ ### 等待异步结果
205
+
206
+ ```bash
207
+ guands dataset refresh <dsId> --wait --timeout 600 # 等待本次刷新到终态
208
+ guands dataset create-db --ac-id <acId> --tables "t1,t2" --wait --timeout 900 --dir-id <dirId> # 等待每张表首次全量抽数
209
+ guands dataset get <dsId> # 查看当前 status / lastExecution
210
+ ```
211
+
212
+ 没有独立的任务命令:不支持按任务 ID 查询、等待或取消任务。等待都以 dsId 为入口,
213
+ 失败原因由 CLI 在进程内部补取并直接展示。
214
+
215
+ ### 目录(Directory)
216
+
217
+ ```bash
218
+ guands dir tree # 查看目录树
219
+ guands dir tree -k ODS --max-depth 3 # 大环境按名称过滤 / 限制深度,避免输出被截断
220
+ guands dir create --name "ODS" --parent <parent_dir_id> # 父目录先在目录树中预检
221
+ guands dir rename <dir_id> --name "新名称" # 保留目录 ID 与父目录,回读树校验生效
222
+ guands dir delete <dir_id> --yes # 目录必须为空
223
+ ```
224
+
225
+ 服务端把目录改名和移动做成了同一个接口且 `parentDirId` 必填,`dir rename` 会先回读
226
+ 该目录当前的父目录一并提交,所以改名不会把目录挪到根目录下。
227
+
228
+ `dir delete` 是**物理删除**,不进回收站、不可恢复。与页面删除(`guanvis page delete`,软删、
229
+ 页面进回收站)不同——但页面那边同样没有 CLI 恢复命令,要还原只能人工登录 BI 网页端。
230
+
231
+ ### 表单目录(Form Folder)
232
+
233
+ 表单目录是 SurveyEngine 的目录,与数据集目录(`dir`)无关。目录功能由 BI 环境的
234
+ survey-engine 服务配置决定(`custom.function.access.folder`),可能开启也可能关闭;
235
+ CLI 自动探测:未开启环境所有表单在根目录(folderId=0),folder 写命令与 `form move`
236
+ 会在发请求前直接拒绝并提示开启方法。
237
+
238
+ ```bash
239
+ guands form folder status # 探测目录功能是否开启(-f json 输出 {"folderEnabled": bool})
240
+ guands form folder tree # 查看表单目录树(两种环境都可用;未开启时为单层)
241
+ guands form folder create --name "巡检" --parent 0 # 创建目录(--parent 缺省为根目录 0)
242
+ guands form folder rename <folderId> --name "新名称" # 重命名(回读树校验生效)
243
+ guands form folder move <folderId> --to <targetId> # 移动目录(禁止移入自身子树;--to 0 为根目录)
244
+ guands form folder delete <folderId> --yes # 删除空目录
245
+ guands form move <fmId1> <fmId2> --to <folderId> # 移动表单到目录,逐个报告成败
246
+ ```
247
+
248
+ ## 输出格式
249
+
250
+ - `--raw`:原样输出当前子命令调用的后端 API JSON;不同 endpoint 的 `response` 结构不同,**不承诺全 CLI 统一 schema**
251
+ - `-f json`:将已转换为表格的查询结果输出为 JSON 数组;目前主要适用于 `list` / `fields` 等表格型命令,**不是 create/import/update 等写命令的统一机器接口**。例外(有固定字段的结果对象):
252
+ - `dataset get <dsId> -f json` → `{dsId, name, displayType, rowCount, colCount, acId, status, description, parentDirId, ctime, utime, fields:[{fdId, name, alias, fdType, metaType, calculationType, formula, source}]}`,`source` 为 `physical`/`calculated`/`group`。当前身份无该数据集读取权限(服务端返回 `hasPermission:false` 的受限对象,不含字段和行列数)、详情为空或缺 `name`/`displayType`/`columns` 时退出码非 0、stdout 不输出,不会给出空的 `fields`;
253
+ - `dataset import … -f json` → `{dsIds:[…], dirId, datasets:[{name, dsId, taskId, status, error}]}`,`dsIds` 与文本输出末行 `dsIds:` 相同;`status` 为 `FINISHED`/`FAILED`/`CANCELED`/`TIMEOUT`/`CREATE_FAILED`/`UNCONFIRMED`,任一项不是 `FINISHED` 时退出码非 0(对象照常输出)。进度、提示与 `-v` 的轮询诊断都走 stderr
254
+ - `-f csv`:CSV 格式输出
255
+ - `-f expanded`:PostgreSQL 风格竖向展开
256
+ - 默认:对齐表格格式,适合 AI 消费
257
+
258
+ 自动化脚本使用 `--raw` 时必须按子命令解析,并在继续调用前断言 ID 非空。常用路径:
259
+
260
+ | 命令 | ID 路径 |
261
+ |---|---|
262
+ | `dataset list --raw` | `.response.contents[].dsId` |
263
+ | `dataset fields <dsId> --raw` | `.response.columns[].fdId` 和 `.response.virtualColumns[].fdId` |
264
+ | `dataset create-db/create-query/import --raw` | `.response[].response.dsId` |
265
+ | `dataset import --raw` 的任务 ID | `.response[].response.taskId` |
266
+
267
+ `dataset list` 的普通查询、`--name`、`--dir-id` 都使用同一搜索 endpoint,当前 `--raw` 均为 `response.contents[]`。
@@ -0,0 +1,157 @@
1
+ # guands 增量更新与定时调度
2
+
3
+ ## ODS 批量抽取工作流(先全量再补增量)
4
+
5
+ 按清单逐表创建抽取数据集,先全量抽取,再配置增量条件。
6
+
7
+ ```bash
8
+ # 1. 确认账号和表
9
+ guands account list
10
+ guands account tables <ac_id>
11
+
12
+ # 2. 创建抽取数据集(全量,不启用增量)
13
+ # BI 会在建集成功后自动触发首次全量抽数,无需手动 refresh
14
+ guands dataset create-db --ac-id <ac_id> --tables "orders" --ds-names "订单表" --dir-id <dir_id>
15
+
16
+ # 3. 等待自动触发的全量抽数完成(不要立即 refresh,会报 5001 任务冲突)
17
+ # 轮询 dataset get 直到状态为 FINISHED;数据量大时适当拉长等待间隔
18
+ guands dataset get <ds_id>
19
+
20
+ # 3b. 如确需再次全量更新(如自动抽数失败后重跑),等状态不再是 UPDATING/WAITING 后执行
21
+ guands dataset refresh <ds_id> --wait
22
+
23
+ # 4. 配置增量更新(先删后插方式,7天回溯,使用时间宏 {{{ expression }}})
24
+ guands dataset update-setting <ds_id> \
25
+ --incremental \
26
+ --incremental-sql "SELECT * FROM orders WHERE data_date >= '{{{today - 7 days}}}'" \
27
+ --preclean \
28
+ --preclean-rule "data_date >= '{{{today - 7 days}}}'"
29
+
30
+ # 5. 或者配置增量更新 + 主键去重方式
31
+ # 增量设置和主键修改是两套独立协议,分别执行
32
+ guands dataset update-setting <ds_id> \
33
+ --incremental \
34
+ --incremental-sql "SELECT * FROM orders WHERE update_time >= '{{{yesterday}}}'"
35
+ guands dataset primary-key set <ds_id> --columns "id"
36
+
37
+ # 6. 验证增量配置
38
+ guands dataset get <ds_id>
39
+ ```
40
+
41
+ **例外情况:数据量太大跳过全量,直接增量补完**
42
+
43
+ ```bash
44
+ # 创建时直接启用增量
45
+ guands dataset create-db --ac-id <ac_id> --tables "big_table" --dir-id <dirId> \
46
+ --incremental \
47
+ --incremental-sql "SELECT * FROM big_table WHERE data_date >= '{{{today - 30 days}}}'" \
48
+ --preclean \
49
+ --preclean-rule "data_date >= '{{{today - 30 days}}}'"
50
+
51
+ # 触发增量更新并等待
52
+ guands dataset refresh <ds_id> --wait
53
+ ```
54
+
55
+ ## 配置定时更新
56
+
57
+ 完成增量配置后,设定定时调度让数据集自动更新:
58
+
59
+ ```bash
60
+ # 每天凌晨 2 点自动增量更新
61
+ guands dataset schedule <ds_id> --cron-type daily --hour 2 --minute 0
62
+
63
+ # 每 4 小时更新一次
64
+ guands dataset schedule <ds_id> --cron-type hourly --interval 4
65
+
66
+ # 每 30 分钟更新一次
67
+ guands dataset schedule <ds_id> --cron-type minute --interval 30
68
+
69
+ # 每周一凌晨 6 点
70
+ guands dataset schedule <ds_id> --cron-type weekly --day-of-week MON --hour 6
71
+
72
+ # 每月 1 号凌晨 3 点
73
+ guands dataset schedule <ds_id> --cron-type monthly --day-of-month 1 --hour 3
74
+
75
+ # 关闭定时更新
76
+ guands dataset schedule <ds_id> --disable
77
+ ```
78
+
79
+ **调度类型说明**:
80
+
81
+ | cron-type | 参数 | 说明 | 示例 |
82
+ |---|---|---|---|
83
+ | `daily` | `--hour`, `--minute` | 每天指定时间执行 | `--hour 2 --minute 30` → 每天 02:30 |
84
+ | `hourly` | `--interval`, `--minute` | 每隔 N 小时执行 | `--interval 4` → 每 4 小时 |
85
+ | `minute` | `--interval` | 每隔 N 分钟执行(最小 5) | `--interval 15` → 每 15 分钟 |
86
+ | `weekly` | `--day-of-week`, `--hour`, `--minute` | 每周指定日期时间 | `--day-of-week MON --hour 6` → 每周一 06:00 |
87
+ | `monthly` | `--day-of-month`, `--hour`, `--minute` | 每月指定日期时间 | `--day-of-month 1 --hour 3` → 每月 1 号 03:00 |
88
+
89
+ - `--day-of-week` 取值:`MON`, `TUE`, `WED`, `THU`, `FRI`, `SAT`, `SUN`(支持逗号分隔多个,如 `MON,WED,FRI`)
90
+ - `--day-of-month` 取值:`1`-`31` 或 `L`(最后一天),支持逗号分隔多个
91
+ - 默认不开启定时,必须显式调用 `schedule` 命令才会打开
92
+ - `schedule` 会先读取数据集当前配置再整体提交 `data-setting`:抽取数据集透传现有增量配置;直连数据集透传现有 `realTimeUpdateSetting` 与 `directConnectUpdateSetting`(服务端对直连缺这两项会报错或清空配置)。WebService(API) 数据集直接拒绝
93
+
94
+ **调度频率限制**:最高 5 分钟一次,低于 1 小时会输出性能警告。建议 ODS 增量至少每小时更新。
95
+
96
+ ## 增量方式选择指南
97
+
98
+ | 增量方式 | 适用场景 | 配置参数 |
99
+ |---|---|---|
100
+ | 先删后插 | 有明确时间分区字段,按时间范围覆盖 | `--preclean --preclean-rule "..."` |
101
+ | 主键去重 | 有唯一主键,新数据覆盖旧数据 | `dataset primary-key set <dsId> --columns "id"` |
102
+ | 全量 | 数据量小或无增量条件 | 不启用 `--incremental` |
103
+
104
+ ## 增量语义限制(重要,配置前必读)
105
+
106
+ 增量更新有两个 BI 服务端固有的语义限制,配置和核数时必须考虑:
107
+
108
+ 1. **主键去重要求主键列非空且唯一**。主键列含 null 时去重行为未定义:建集和 refresh 时可能把多个 null-key 行折叠成一行(静默丢行),也可能产生重复,且全程不会报错。执行 `dataset primary-key set` 前先确认源表该列无 null(脏数据需先清洗或换主键列)。主键修改会触发异步数据重写,CLI 默认等待任务完成并回读验证;清空主键使用 `dataset primary-key clear`。
109
+ 2. **时间窗口增量没有 DELETE 语义**。增量 SQL 按 `updated_at >= {{{时间宏}}}` 只能拉到新增/更新的行,源表物理删除的行会在 BI 数据集中永久残留。源表会删行(退单/撤销/物理删除)的场景,需要:
110
+ - 周期性全量更新兜底(`dataset refresh --overwrite` 或定时全量),或
111
+ - 用 preClean 先删后插并保证删除发生在 preClean 覆盖的时间窗口内。
112
+
113
+ 另外注意:数据集的 **schema 在建集时冻结**,默认 refresh 不同步源端结构变化:
114
+ - 源表 `ADD COLUMN` 后 refresh 不会带入新列(refresh 仍报成功)
115
+ - 源表 `DROP COLUMN` 后 refresh 仍报成功,但该列值会全部变 null(静默清空)
116
+
117
+ 两种处理方式(无需重建数据集):
118
+ - **日常加列场景**:`dataset update-setting <dsId> --auto-sync-schema on` 开启"自动更新数据结构",之后每次更新检测到源端新增列会自动加入(缺列时结构保持不变,不能处理删列/改名)。抽取数据集该开关挂在增量配置下,需增量启用才生效;直连数据集直接生效
119
+ - **删列/改名/改类型或一次性结构对齐**:用 `dataset sync-schema` 走完整"更新模型结构"流程(见下方工作流),改名字段保留 fdId、下游卡片引用不断
120
+
121
+ ## 时间宏使用说明
122
+
123
+ 增量 SQL 和 preClean 规则中**必须使用 BI 时间宏**(而非 `CURDATE()`、`CURRENT_DATE` 等数据库函数),
124
+ 这样 BI 在执行更新时会自动替换为当前日期值。
125
+
126
+ **时间宏语法**:`{{{ expression }}}`(三花括号包裹表达式)
127
+
128
+ ```
129
+ # 正确 ✓ — 使用 BI 时间宏(三花括号)
130
+ SELECT * FROM orders WHERE data_date >= '{{{today - 7 days}}}'
131
+ SELECT * FROM orders WHERE update_time >= '{{{yesterday}}}'
132
+ SELECT * FROM orders WHERE create_date >= '{{{first day of this month}}}'
133
+
134
+ # 错误 ✗ — 使用数据库函数(不会被 BI 识别和管理)
135
+ SELECT * FROM orders WHERE data_date >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
136
+ ```
137
+
138
+ **常用时间宏表达式**:
139
+
140
+ | 表达式 | 含义 | 示例结果(假设今天 2026-03-31) |
141
+ |---|---|---|
142
+ | `{{{today}}}` | 今天 | 2026-03-31 |
143
+ | `{{{yesterday}}}` | 昨天 | 2026-03-30 |
144
+ | `{{{today - 1 days}}}` | 昨天(等同 yesterday) | 2026-03-30 |
145
+ | `{{{today - 7 days}}}` | 7 天前 | 2026-03-24 |
146
+ | `{{{today - 30 days}}}` | 30 天前 | 2026-03-01 |
147
+ | `{{{first day of this month}}}` | 本月第一天 | 2026-03-01 |
148
+ | `{{{first day of last month}}}` | 上月第一天 | 2026-02-01 |
149
+ | `{{{last day of last month}}}` | 上月最后一天 | 2026-02-28 |
150
+ | `{{{today - 1 months}}}` | 一个月前 | 2026-02-28 |
151
+ | `{{{monday}}}` | 本周一 | 2026-03-30 |
152
+
153
+ **注意**:时间宏与动态参数是两套不同的机制:
154
+ - **时间宏** `{{{ expr }}}` — 由 `time_macro` 库在 SQL 执行前自动解析替换,无需预先定义
155
+ - **动态参数** `[DYNAMIC_PARAMS.name]` — 需要在 BI 中预先创建参数实体,适用于用户交互式筛选
156
+
157
+ 增量 SQL 场景应使用**时间宏**。