在图数据库开发中,数据类型的正确使用是构建高效模型的基础。NebulaGraph 支持丰富的数据类型,其中日期时间体系因涉及时区转换、格式匹配等细节,常成为开发者关注的焦点。本文将系统梳理 NebulaGraph 的数据类型,结合具体代码示例和应用场景,帮助大家精准掌握各类用法及注意事项。
一、数值类型:精度控制与存储规则详解
1. 整数类型:隐藏的类型统一机制
NebulaGraph 支持 4 种整数类型,需特别注意存储与查询时的类型转换规则:
ngql
// 定义不同整数类型属性
CREATE TAG int_types (
age INT8, // 8位整数,范围-128~127
score INT16, // 16位整数,范围-32768~32767
population INT32, // 32位整数,范围±21亿+
user_id INT // INT为INT64别名,支持全范围64位整数
);
// 插入数据时,非INT64类型属性最终以INT64返回
INSERT VERTEX int_types(age, score, population, user_id)
VALUES "100":(127, 32767, 2147483647, 9223372036854775807);
// 查询结果显示所有整数属性均为INT64类型
FETCH PROP ON int_types "100"
YIELD int_types.age, int_types.score, int_types.population, int_types.user_id;
🔍 核心特性:
- VID 限制:仅 INT64 和定长字符串可作为 VID,其他整数类型作为 VID 会报错
- 类型统一:无论定义为何种整数类型,查询结果统一为 INT64,跨语言开发需注意类型映射
- 范围校验:插入超范围值会直接失败,建议在应用层提前进行数值检查
2. 浮点数类型:精度与科学计数法支持
浮点数包括单精度 FLOAT 和双精度 DOUBLE,支持多种科学计数格式:
ngql
// 定义浮点类型属性
CREATE TAG float_types (
pi FLOAT, // 单精度,6~7位有效数字
e DOUBLE // 双精度,15~16位有效数字
);
// 支持科学计数法插入
INSERT VERTEX float_types(pi, e)
VALUES "200":(3.1415e0, 2.718281828459045e0),
"201":(.9e1, 1.e3); // 等价于9和1000
// 浮点数转整数时自动四舍五入
UPDATE VERTEX "200" SET float_types.pi = 3.9; // 实际存储为4
⚠️ 注意事项:
- 精度丢失:FLOAT 无法精确表示部分小数(如 0.1),金融计算建议使用 DOUBLE
- 类型转换:FLOAT 赋值给 DOUBLE 安全,反向操作可能导致精度损失
- 存储格式:所有进制输入均转为十进制存储,如 0x1e240 会转换为 123456
二、字符串类型:定长与变长的应用场景对比
1. 定长字符串 FIXED_STRING:长度限制的双刃剑
定长字符串在定义时指定长度,插入时超长处理规则因场景而异:
ngql
// 创建定长字符串属性(长度10)
CREATE TAG fixed_name (name FIXED_STRING(10));
// 插入刚好长度的字符串
INSERT VERTEX fixed_name(name) VALUES "300":"nebula"; // 正常插入
// 插入超长字符串:作为属性时截断,作为VID时报错
INSERT VERTEX fixed_name(name) VALUES "301":"nebulagraph"; // 截断为前10位"nebulagrap"
INSERT VERTEX "302" OF fixed_name (name) VALUES "toolongname"; // 报错!VID不允许截断
📌 使用建议:
- 属性场景:适合存储长度固定的字段(如 ID、编码),超长时自动截断(可能丢失数据)
- VID 场景:严格校验长度,确保图结构中节点标识的唯一性
- 性能优势:定长存储提升查询效率,尤其在频繁过滤场景中表现突出
2. 变长字符串 STRING:灵活处理动态内容
变长字符串支持任意长度(受限于存储引擎),需注意特殊字符转义:
ngql
// 创建变长字符串属性
CREATE TAG description (desc STRING);
// 包含特殊字符时需转义
INSERT VERTEX description(desc) VALUES "400":"He said, \"Hello World\""; // 转义双引号
INSERT VERTEX description(desc) VALUES "401":"C:\\NebulaGraph\\data"; // 转义反斜杠
// 字符串比较区分大小写
MATCH (v:description) WHERE v.description.desc STARTS WITH "He" RETURN v;
🔧 最佳实践:
- 转义规则:仅支持
\"
和\\
转义,其他特殊字符需通过函数处理 - Schema 命名:可作为图空间、Tag 等名称,而固定字符串仅限属性定义
- 索引设计:大小写敏感,创建全文索引时需统一处理字符格式
三、日期时间类型:时区转换与函数应用全解析
1. 基础时间类型:格式规范与范围限制
NebulaGraph 支持 5 种时间相关类型,需严格遵循格式要求:
ngql
// 创建包含多种时间类型的标签
CREATE TAG time_data (
event_date DATE, // 日期格式YYYY-MM-DD,范围-32768-01-01~32767-12-31
event_time TIME, // 时间格式hh:mm:ss.ms(微秒级精度)
event_datetime DATETIME, // 日期时间组合,带时区信息
event_timestamp TIMESTAMP, // 时间戳存储为64位整数
event_duration DURATION // 时间间隔,用Map表示{years:1, days:3}
);
// 插入时间数据示例
INSERT VERTEX time_data(event_date, event_time, event_datetime, event_timestamp) VALUES "500":(
date("2023-12-31"), // 日期
time("23:59:59.999999"), // 最大时间值
datetime("2024-01-01T08:30:00+08:00"), // 带时区的日期时间
timestamp("2024-01-01T00:00:00") // 时间戳转换
);
🌐 时区处理核心逻辑:
- 全局配置:所有节点
conf/time.conf
中的timezone_name
必须一致,默认转换为 UTC 存储 - 函数转换:
datetime()
支持时区参数,如datetime("2017-03-04T22:30:40.003000[Asia/Shanghai]")
- 精度支持:TIME 和 DATETIME 支持微秒级精度,TIMESTAMP 底层为 64 位整数存储
2. 时间戳 TIMESTAMP:两种插入方式对比
ngql
// 方式1:直接插入Unix时间戳整数(UTC时间)
INSERT VERTEX school(found_time) VALUES "DUT":(573206400); // 对应1988-03-01T08:00:00 UTC
// 方式2:通过timestamp()函数转换日期字符串
INSERT VERTEX school(found_time) VALUES "DUT":(timestamp("1988-03-01T08:00:00"));
// 获取当前时间戳(两种等价方式)
UPDATE VERTEX "DUT" SET school.found_time = timestamp();
UPDATE VERTEX "DUT" SET school.found_time = now();
⚙️ 高级用法:
- 时间运算:支持
date + duration
、timestamp - timestamp
等表达式,返回时间间隔 - 属性提取:通过
date().month
、datetime().hour
等函数获取时间分量,用于分组统计 - 范围查询:利用时间戳整数特性,可直接进行数值范围过滤,提升查询效率
3. 时间间隔 DURATION:复杂时间计算解决方案
ngql
// 定义DURATION类型属性(非存储属性,用于计算)
// 创建包含时间间隔的查询
WITH
date("2023-01-01") AS start_date,
duration({years:2, months:3, days:10}) AS delta
RETURN start_date + delta; // 结果为2025-04-11
// 计算两个日期的间隔
RETURN date("2023-12-31") - date("2023-01-01"); // 返回364(天数差)
💡 应用场景:
- 计算事件持续时间、有效期等场景,通过 Map 结构灵活组合年 / 月 / 日 / 时 / 分 / 秒
- 不支持作为存储属性,需在查询时动态生成,用于时间偏移计算
四、复合数据类型:建模方式与使用限制
1. 列表(List):查询中的临时数据处理
ngql
// 列表不能作为属性存储,但可在查询中使用
MATCH (v:player)
WITH collect(v.player.name) AS name_list // 收集节点名称列表
RETURN
name_list[0], // 第一个元素(下标0开始)
name_list[-1], // 最后一个元素(下标-1)
name_list[1..3] // 下标1到2的元素(左闭右开)
🚫 禁止操作:
- 严禁在
CREATE TAG
中定义列表类型属性,会触发Composite type is not supported
错误 - 下标越界时返回
OUT_OF_RANGE
,需在应用层进行边界检查
2. 集合(Set)与映射(Map):无序性与键值规则
ngql
// 集合自动去重且无序
RETURN set{1,2,1} AS unique_set; // 结果为{1,2},顺序不固定
// 映射的键必须为字符串类型
YIELD map{name: "Nebula", version: "3.6"} AS valid_map; // 正确
YIELD map{1: "invalid"} AS invalid_map; // 报错!键必须是字符串
🔄 替代方案:
- 若需存储多值属性(如用户兴趣),建议创建独立节点,通过边连接主节点与兴趣节点
- 映射可用于临时数据聚合(如 WITH 语句中的中间变量),但永久存储需拆解为独立属性
五、类型转换:显性函数与隐性规则
NebulaGraph 支持显式类型转换,需注意转换失败时返回 NULL:
ngql
// 常用转换函数
RETURN
toInteger("123"), // 123
toFloat("1.2"), // 1.2
toBoolean("true"), // true
toInteger("abc"); // NULL(转换失败)
// 浮点数转整数的四舍五入规则
INSERT VERTEX score(level) VALUES "600":(3.9); // 实际存储为4(3.9四舍五入为4)
📝 最佳实践:
- 所有外部输入数据需经过格式校验,避免无效转换导致数据丢失
- 复杂转换逻辑建议在应用层处理,保持数据库层的类型纯净性
总结:构建健壮图模型的核心原则
- 类型匹配优先:根据业务需求选择类型,如高频 ID 查询用定长字符串,时间范围检索用 TIMESTAMP
- 文档清晰化:在 Schema 设计中明确标注每个属性的类型、范围、默认值,例如:
plaintext
user_profile: - user_id: FIXED_STRING(32) (必填,节点VID) - birth_year: INT16 (范围1900~2100,默认1970) - register_time: TIMESTAMP (自动赋值当前时间戳)
- 测试覆盖:对每个新定义的类型组合进行全流程测试(插入、查询、更新、删除),确保行为符合预期
掌握 NebulaGraph 的数据类型体系,能帮助我们避免底层设计缺陷,提升图数据库的使用效率。在实际开发中,建议结合官方文档与具体业务场景,提前规划类型使用方案。如果你在实践中遇到特殊类型问题,欢迎在评论区留言讨论,共同探索最优解决方案。觉得本文有帮助的话,别忘了收藏关注,后续将持续分享图数据库开发的实用技巧!