GDIM数据更新 (Data Update)
本章说明如何为 GDIM 表格模板配置 中表格属性里的 「自定义数据更新配置」 编写 Pipeline。 平台界面和部分文档里,同一功能也可能写作 「表格数据更新」 或 「数据更新」。
这类应用和普通「把结果立刻写回 GDIM 表」的 Pipeline 不是同一种运行契约:
GDIM 先把 Pipeline 当 预览 跑一遍,用户核对返回的表之后,再由 前端 写入。
上传的 .pipe 在这次预览运行里 不得 自己写库。
Note
平台界面称「数字模型」,SDK 中仍多写作 template / 「模板」,见
术语对照。
适用场景
把 Pipeline 做成「自定义数据更新配置」应用,通常是为了:
用一张源表的字段去更新或补齐另一张目标表(例如把标准地层的岩性、密实度同步到岩土参数建议值表);
先让用户在界面上看到合并后的预览表,确认后再写入;
在 子表 上只更新当前主表主键范围内的行(此时还要配合
auto_bind="pk_field")。
如果目标是脚本或普通应用 运行时立即写库,继续用 GdimTableWriter 的默认行为(auto_run=True)即可,
见 新手入门 (Getting Started) 和 modules.writers 模块帮助 中 GdimTableWriter 的普通写入示例。
不要把本章的预览约定套到那种 Pipeline 上。
平台如何运行
用户在数字模型里配置「自定义数据更新」,并挂上你上传的
.pipe。GDIM 运行 Pipeline 做预览,读取
return_results_config指定的表端口,把结果展示给用户。用户核对后点击确认,**由前端写入**目标表;预览这次运行里 Pipeline 不应再调用写入接口。
因此 Pipeline 要同时满足:
**预览结果**是一张(或一组)带好
gdim_id、且包含**前端写库所需业务列**的表,通常来自MergeGdimTables.OutputTables;不必为了预览而读取或返回 GDIM 模板中的全部字段(见下文「预览字段与墓碑行」)。保存进
.pipe的图里不能有GdimTableWriter。平台恢复时会把所有模块auto_run设为True,不能靠auto_run=False挡住写入。
推荐拓扑
主表场景的典型数据流:
GdimTableReader (源表)
│ OutputTable
▼
RenameTableColumns / 其它整形模块 (把源表对齐到目标表名、列名)
│
├──────────────────────────────┐
▼ ▼
MergeGdimTables.InputTables GdimTableReader (目标表, keep_gdim_id=True)
│ OutputTables
▼
MergeGdimTables.InputGdimTables
│
▼
MergeGdimTables.OutputTables ← 预览端口
│
(仅本地写回测试时,save_pipeline 之后再接)
▼
GdimTableWriter.InputData
要点:
目标表读取必须
keep_gdim_id=True,这样合并结果才能区分插入 / 更新。MergeGdimTables以 InputGdimTables 侧读入的列结构 为输出 schema,并补齐gdim_id;how、join_key按业务选择(1:1 更新常用overwrite+ 业务键)。return_results_config**必须**指向预览表端口,例如{"MergeGdimTables": "OutputTables"}。GdimTableWriter没有面向用户的输出端口,不能当作预览结果。源表或目标表可能为空时,把对应
GdimTableReader.empty_error_type设为"create_empty_table",避免预览直接失败。
预览字段与墓碑行(前端写入 vs GdimTableWriter)
自定义数据更新(本章) 由 GDIM **前端**在用户确认后写库,Pipeline 只负责返回预览表:
**只需返回前端更新所需的字段**(以及区分插入 / 更新所需的
gdim_id)。GdimTableReader.table_fields可以只列出本次要改的业务列,MergeGdimTables预览结果也只需携带这些列。墓碑行如何删除由前端控制。 例如
MergeGdimTables在 1:Noverwrite等场景下会输出「保留gdim_id、预览表内业务列均为空」的行;用户确认后,前端会按平台规则处理删除(例如预览行在更新后整行业务字段为空时删除对应 GDIM 记录)。Pipeline **不必**为上传预览而读取 GDIM 模板的全部列。
仅在 Pipeline 内通过 ``GdimTableWriter`` 直接写库、且要靠墓碑行触发 ``delete_table_data`` 删整行时,才需要关心写入载荷是否覆盖 GDIM 模板中的**全部业务字段**(完整 schema 墓碑行、delete_tombstone_rows 等)。那属于 modules.writers 模块帮助 中「立即写回 / SDK Writer」的约定,**不是**本章「前端确认后写入」的默认要求。
本地在 save_pipeline() 之后临时接 GdimTableWriter 做写回测试时,若测试方式与线上一致(只写预览里的部分列),同样按前端契约理解删除行为即可;若希望 Writer 在本地走 delete_table_data 删整行,再按 modules.writers 模块帮助 准备完整 schema 载荷。
保存的 .pipe 不能连接 GdimTableWriter
在 build_pipeline() 里不要实例化、也不要连接 GdimTableWriter。
save_pipeline() 完成后再按需临时接上 writer 做本地写回测试。
这样上传到 GDIM 的 .pipe 只有「读 → 合并 → 返回预览表」,平台预览时不可能误写库。
不能把 writer 留在图里再设 auto_run=False。GDIM 加载 .pipe 时会把 所有模块的 auto_run 都改回 True,
预览运行就会写库。
两种场景对比:
写法 |
保存的 |
适用 |
|---|---|---|
|
图中无 |
「自定义数据更新配置」;GDIM 预览,前端确认后写入 |
普通立即写回 |
writer 默认 |
数据处理应用、导入脚本等,运行即写库;**不是**本章功能 |
本地用 pipeline.run() 取预览表时,必须传入 return_results=pipeline.return_results_config。
默认收集的是末端模块端口;若之后接了没有输出端口的 writer,get_result("MergeGdimTables", "OutputTables") 会得到 None,即使合并已经成功。
主表完整示例
下面把标准地层表的若干字段按 layer_number 同步到岩土参数建议值表:
建议值表里已有、但标准地层表没有的层号予以保留。保存的 .pipe 不连接 writer;
本地若要真正写回,在 save_pipeline() 之后再临时接线。
from pathlib import Path
from gdisdk.connectors import log_in
from gdisdk.modules import (
GdimTableReader,
GdimTableWriter,
MergeGdimTables,
RenameTableColumns,
)
from gdisdk.pipeline import PipeLine
SOURCE_TABLE = "standard_layer_table"
TARGET_TABLE = "proposed_geotechnical_parameters_table"
TARGET_TABLE_TITLE = "岩土参数建议值表"
SYNC_FIELDS = [
"layer_number",
"material_name",
"compactness",
"plastic_state",
"weathering_degree",
]
_SCRIPT_DIR = Path(__file__).resolve().parent
WORKSPACE_DIR = _SCRIPT_DIR / "workspace"
def build_pipeline() -> PipeLine:
pipeline = PipeLine(
app_name="geoParamsPropose1",
app_title="同步标准地层到岩土参数建议值表",
description="按 layer_number 把标准地层字段更新或插入岩土参数建议值表",
workspace=WORKSPACE_DIR,
)
pipeline.update_gdim_state(token=log_in(), proj_id="你的GDIM项目ID")
read_standard = GdimTableReader("ReadStandardLayer")
read_standard.table_fields = {SOURCE_TABLE: SYNC_FIELDS}
read_standard.output_table_name = SOURCE_TABLE
read_standard.empty_error_type = "create_empty_table"
read_proposed = GdimTableReader("ReadProposedParams")
read_proposed.table_fields = [TARGET_TABLE]
read_proposed.keep_gdim_id = True
read_proposed.empty_error_type = "create_empty_table"
rename_source = RenameTableColumns("RenameSourceTable")
rename_source.table_name = TARGET_TABLE
rename_source.table_title = TARGET_TABLE_TITLE
merge_tables = MergeGdimTables("MergeGdimTables")
merge_tables.how = "overwrite"
merge_tables.join_key = "layer_number"
merge_tables.auto_map_columns = False
links = (
read_standard.OutputTable >> rename_source.InputTable
| rename_source.OutputTable >> merge_tables.InputTables
| read_proposed.OutputTables >> merge_tables.InputGdimTables
)
pipeline.add_links(links)
pipeline.return_results_config = {"MergeGdimTables": "OutputTables"}
pipeline.save_pipeline(f"{pipeline.workspace}/{pipeline.app_name}.pipe")
return pipeline
if __name__ == "__main__":
pipeline = build_pipeline()
result = pipeline.run(
verbose=True,
run_trace_file="run_trace.json",
return_results=pipeline.return_results_config,
)
print(result.get_result("MergeGdimTables", "OutputTables"))
# 仅本地写回测试:save_pipeline() 之后再接线,不要把这段写进要上传的 .pipe
# write_proposed = GdimTableWriter("WriteProposedParams")
# write_proposed.table_names = TARGET_TABLE
# merge_tables = pipeline.get_module("MergeGdimTables")
# pipeline.add_links(merge_tables.OutputTables >> write_proposed.InputData)
# pipeline.run(return_results=pipeline.return_results_config)
子表还需要 auto_bind="pk_field"
若更新的是数字模型 子表,并且希望 GDIM 用「更新范围」下拉框注入 主表主键列表 (例如只更新若干钻孔下的地层行),在上述预览约定之外,再给读取模块加上:
pipeline.add_attribute(
attr_name="primary_key_value_filter",
module_name="ReadTable",
param_name="primary_key_value_filter",
attr_title="钻孔编号",
auto_bind="pk_field",
)
这只是额外的前端注入,**不能代替**「预览端口 + 保存的 .pipe 不写库」。
运行时值始终是
list[主键数据类型]``(例如 ``["ZK1"]或[]),不要按标量处理。主表上的自定义更新会忽略该机制,属性按普通控件渲染。
完整约定见 用户指南 (User Guide) 中「子表按主键更新(pk_field)」一节。
常见错误
预览端口指错。
return_results_config指向GdimTableWriter,或设为True把所有末端输出都丢给前端。应指向合并后的预览表。上传的
.pipe会写库。save_pipeline()前连接了GdimTableWriter。平台恢复时会把所有模块auto_run设为True,即使用户本地写成了False,预览也会写库。把本地写回测试写进
.pipe。 writer 只能出现在save_pipeline()之后的测试块里。指望
auto_run=False挡住写入。 这对上传后的 GDIM 预览无效。本地
get_result为None。run()未传return_results=pipeline.return_results_config。更新变成插入。 目标表读取未设
keep_gdim_id=True,或合并前丢掉了gdim_id。子表更新了整张表。 漏了
auto_bind="pk_field",或绑定参数只接受单个主键而不是列表。把本章约定用到普通写回应用。 立即写库的 Pipeline 应保持
GdimTableWriter.auto_run=True。误以为预览必须带 GDIM 模板全部列。 上传给「自定义数据更新」的 Pipeline 只需返回前端要改的字;完整 schema 墓碑行只在 Writer 直接写库且要 SDK 删整行 时才需要,见上文「预览字段与墓碑行」。
与其它文档的关系
MergeGdimTables的匹配键、overwrite/ 墓碑行:modules.mergers 模块帮助GdimTableWriter的插入 / 更新 / 删除与普通立即写回:modules.writers 模块帮助子表
auto_bind="pk_field":用户指南 (User Guide)、UI控件 (UI Schema)、运行机制 (Runtime)上传前总清单:上传GDIM检查 (GDIM Upload Check)
在页面上核对表名 / 字段名:GDIM开发模式 (Dev Mode)