跳到主要内容

STRUCT 类型数据导入

STRUCT<field_name:field_type [COMMENT 'comment_string'], ... > 表示由多个 Field 组成的结构体,也可被理解为多个列的集合。更多类型说明请参见 STRUCT 数据类型

本文从典型用户场景出发,介绍如何将 STRUCT 数据导入 Apache Doris,覆盖以下两类常见数据格式:

  • CSV 格式导入:适用于从文本文件、ETL 任务输出等场景导入。
  • JSON 格式导入:适用于从 API、日志或半结构化数据源导入。

两种方式都通过 Stream Load 完成,也支持通过 INSERT INTO VALUES 语句直接写入。

导入流程概览

无论使用何种数据格式,导入 STRUCT 类型数据均遵循以下 4 个步骤:

步骤操作说明
1准备数据按目标格式(CSV / JSON)构造测试数据文件
2在数据库中建表创建包含 STRUCT 字段的表结构
3导入数据使用 Stream Load 或 INSERT INTO 写入
4检查导入数据通过 SELECT 验证结果

CSV 格式导入

第 1 步:准备数据

创建如下 CSV 文件 test_struct.csv。其中分隔符使用 | 而不是逗号,以便和 STRUCT 内部的逗号区分。

1|{10, 3.14, "Emily"}
2|{4, 1.5, null}
3|{7, null, "Benjamin"}
4|{}
5|null

第 2 步:在数据库中建表

CREATE TABLE struct_test (
id INT NOT NULL,
c_struct STRUCT<f1:INT,f2:FLOAT,f3:STRING> NULL
)
DUPLICATE KEY(id)
DISTRIBUTED BY HASH(id) BUCKETS 1
PROPERTIES (
"replication_allocation" = "tag.location.default: 1"
);

第 3 步:导入数据

使用 Stream Load 导入 CSV 文件:

curl --location-trusted \
-u "root":"" \
-H "column_separator:|" \
-H "columns: id, c_struct" \
-T "test_struct.csv" \
http://localhost:8040/api/testdb/struct_test/_stream_load

也可以使用 INSERT INTO VALUES 语句导入:

INSERT INTO struct_test VALUES(1, named_struct('f1', '1', 'f2', '2.0', 'f3', 'abc'));

第 4 步:检查导入数据

mysql> SELECT * FROM struct_test;
+------+--------------------------------------+
| id | c_struct |
+------+--------------------------------------+
| 1 | {"f1":10, "f2":3.14, "f3":"Emily"} |
| 2 | {"f1":4, "f2":1.5, "f3":null} |
| 3 | {"f1":7, "f2":null, "f3":"Benjamin"} |
| 4 | {"f1":null, "f2":null, "f3":null} |
| 5 | NULL |
+------+--------------------------------------+
5 rows in set (0.01 sec)

JSON 格式导入

第 1 步:准备数据

创建如下 JSON 文件 test_struct.json

[
{"id":1, "c_struct":{"f1":10, "f2":3.14, "f3":"Emily"}},
{"id":2, "c_struct":{"f1":4, "f2":1.5, "f3":null}},
{"id":3, "c_struct":{"f1":7, "f2":null, "f3":"Benjamin"}},
{"id":4, "c_struct":{}},
{"id":5, "c_struct":null}
]

第 2 步:在数据库中建表

CREATE TABLE struct_test (
id INT NOT NULL,
c_struct STRUCT<f1:INT,f2:FLOAT,f3:STRING> NULL
)
DUPLICATE KEY(id)
DISTRIBUTED BY HASH(id) BUCKETS 1
PROPERTIES (
"replication_allocation" = "tag.location.default: 1"
);

第 3 步:导入数据

使用 Stream Load 导入 JSON 文件,需通过 format:json 指定格式,并通过 strip_outer_array:true 解析最外层 JSON 数组:

curl --location-trusted \
-u "root":"" \
-H "format:json" \
-H "columns: id, c_struct" \
-H "strip_outer_array:true" \
-T "test_struct.json" \
http://localhost:8040/api/testdb/struct_test/_stream_load

第 4 步:检查导入数据

mysql> SELECT * FROM struct_test;
+------+--------------------------------------+
| id | c_struct |
+------+--------------------------------------+
| 1 | {"f1":10, "f2":3.14, "f3":"Emily"} |
| 2 | {"f1":4, "f2":1.5, "f3":null} |
| 3 | {"f1":7, "f2":null, "f3":"Benjamin"} |
| 4 | {"f1":null, "f2":null, "f3":null} |
| 5 | NULL |
+------+--------------------------------------+
5 rows in set (0.00 sec)

关键参数说明

下表列出 STRUCT 导入过程中常用的 Stream Load Header 参数:

参数适用格式说明
column_separatorCSV列分隔符。STRUCT 内部使用 ,,建议外层使用 `
columnsCSV / JSON指定列与表字段的映射关系
formatJSON指定导入文件格式为 json
strip_outer_arrayJSON当 JSON 文件最外层为数组时设为 true,以按行解析

常见问题

1. 为何 CSV 文件中需要使用 | 而不是 , 作为分隔符?

STRUCT 字段的字面量内部使用 , 分隔各个 Field(例如 {10, 3.14, "Emily"})。如果外层列分隔符也使用 ,,会与 STRUCT 内部分隔符冲突,导致解析错误。建议改用 |\t 等不会出现在 STRUCT 内部的字符。

2. 如何在 SQL 中直接插入 STRUCT 值?

使用 named_struct 函数显式指定每个 Field 的名称与值,例如:

INSERT INTO struct_test VALUES(1, named_struct('f1', '1', 'f2', '2.0', 'f3', 'abc'));

3. STRUCT 字段允许哪些 NULL 形式?

数据形式含义
null整个 STRUCT 列为 NULL
{}STRUCT 存在,但所有 Field 为 NULL
{10, null, "Emily"}部分 Field 为 NULL,其余正常赋值

4. JSON 导入为何要设置 strip_outer_array:true

当 JSON 文件以数组形式包裹多条记录(如 [ {...}, {...} ])时,需要通过 strip_outer_array:true 让 Doris 去掉最外层数组并按行解析;否则导入会按整个数组作为单条记录处理。