最近更新时间:2025-11-11 11:51:48
AGE 使用一种名为 agtype 的自定义数据类型,这是图查询与结果返回中唯一使用的数据类型。
agtype 是 JSON 的超集,同时也是 JSONB 的自定义实现。它在保留 JSON 结构化表达能力的基础上,支持更多适用于图数据的特性,例如:
对节点(Vertex)、边(Edge)和路径(Path)的结构化表达;
支持图属性(Properties)的键值对存储;
可与 PostgreSQL 的原生类型相互转换,实现无缝交互。
在 Cypher 中,null 表示缺失值或未定义的值。 从概念上讲,null 代表“未知的缺失值”,其行为与普通数据值不同。
当尝试访问不存在的属性时,将返回 null。
任何以 null 作为输入的表达式通常会返回 null。
在 WHERE 子句中,若布尔表达式的计算结果为 null,将被视为 false。
null 不等于 null。因为“未知的两个值”不能被认定为相同,所以表达式 null = null 的结果为 null,而非 true。
输入/输出格式
查询示例:
SELECT *
FROM cypher('graph_name', $$
RETURN NULL
$$) AS (null_result agtype);查询结果:
null_result |
(1 row) |
agtype 类型中的 NULL 与 PostgreSQL 原生的 NULL 在概念上保持一致,二者都遵循 Cypher 查询语言 的语义规则:
均表示“缺失或未知”的值,并在逻辑计算中遵循相同的三值逻辑(true / false / null)。
整数类型存储整数,即没有小数部分的数字。整数数据类型是一个 64 位字段,存储从 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 的值。尝试存储超出此范围的值将导致错误。
整数类型是常见的选择,因为它在范围、存储大小和性能之间提供了平衡。smallint 类型通常仅在磁盘空间宝贵时使用。bigint 类型设计用于整数类型的范围不足时使用。
输入/输出格式
查询示例:
SELECT *
FROM cypher('graph_name', $$
RETURN 1
$$) AS (int_result agtype);查询结果:
int_result |
1 |
(1 row) |
数据类型 float 是一个不精确的、可变精度的数值类型,符合 IEEE-754 标准。
由于浮点数采用二进制近似存储,某些数值无法被精确表示,因此存储与检索的值可能存在细微差异。这种误差的累积与传播属于数值计算领域的问题,此处仅需注意以下几点:
如果您需要精确的存储和计算(例如货币金额),请改用数值类型。
如果您想对这些类型进行重要内容的复杂计算,特别是如果您依赖边界情况(无穷大、下溢)中的某些行为,您应该仔细评估实现。
比较两个浮点值是否相等可能并不总是按预期工作。
当值过大或过小超出浮点表示范围时,将导致错误。输入精度高时,系统可能自动执行舍入。若数值过于接近零而无法区分,将触发下溢(underflow)错误。
特殊值说明
除常规数值外,float 类型还支持以下 IEEE-754 特殊值:
特殊值 | 含义 |
| 正无穷大 |
| 负无穷大 |
| 非数字(Not a Number) |
这些分别表示 IEEE 754 特殊值"无穷大"、"负无穷大"和"非数字"。在 Cypher 命令中将这些值写为常量时,您必须用引号括起来并转换它们,例如:
SET x.float_value = '-Infinity'::float在输入时,这些字符串以不区分大小写的方式识别。
注意 IEEE754 指定 NaN 不应等于任何其他浮点值(包括 NaN)。但是,为了允许浮点数正确排序,AGE 将 'NaN'::float = 'NaN'::float 评估为 true。有关更多详细信息,请参见可比性和相等性章节。
输入/输出格式
要使用浮点数,请表示十进制值。
查询示例:
SELECT *
FROM cypher('graph_name', $$
RETURN 1.0
$$) AS (float_result agtype);查询结果:
float_result |
1.0 |
(1 row) |
numeric 类型用于存储高精度数值,尤其适合需要精确计算的场景,如货币金额、统计结果或科学计算。该类型可在加、减、乘等运算中生成完全精确的结果,但计算性能通常低于整数或浮点类型。
关于数值的精度与标度(Precision & Scale):
精度(Precision):数字中有效位数的总数(包括小数点两侧的所有位数)。
标度(Scale):小数部分的位数,即小数点右侧的数字位数。
例如:数值 23.5141 的精度为 6,标度为 4。整数可视为标度为 0 的数值。
如果没有任何精度或小数位数,则会创建一个列,其中可以存储任何精度和小数位数的数值,可达精度的代码实现限制。这种列不会将输入值强制转换为任何特定标度,而具有声明标度的数值列会将输入值强制转换为该标度。(SQL 标准要求默认标度为 0,即强制转换为整数精度。我们发现这有点无用。如果您关心可移植性,请始终明确指定精度和标度。)
如果要存储的值的标度大于列的声明标度,系统会将值舍入到指定的小数位数。然后,如果小数点左侧的数字数超过声明的精度减去声明的标度,则会引发错误。
数值在物理上存储时没有任何额外的前导或尾随零。因此,列的声明精度和标度是最大值,而不是固定分配。(从这个意义上说,数值类型更像 varchar(n) 而不是 char(n)。)实际存储要求是每四个十进制数字组两个字节,加上三到八个字节的开销。
除了普通数值外,数值类型还允许特殊值 NaN,意思是"非数字"。对 NaN 的任何操作都会产生另一个 NaN。在 SQL 命令中将此值写为常量时,您必须用引号括起来,例如 UPDATE table SET x = 'NaN'。
在"非数字"概念的大多数实现中,NaN 被认为不等于任何其他数值(包括 NaN)。但是,为了允许浮点数正确排序,AGE 将 'NaN'::numeric = 'NaN':numeric 评估为 true。有关更多详细信息,请参见可比性和相等性部分。
在舍入值时,数值类型将平局舍入远离零,而(在大多数机器上)实数和双精度类型将平局舍入到最近的偶数。
输入/输出格式:
创建数值数据类型时,需要 ::numeric 数据注释。
查询示例:
SELECT *
FROM cypher('graph_name', $$
RETURN 1.0::numeric
$$) AS (numeric_result agtype);查询结果:
numeric_result |
1.0::numeric |
(1 row) |
AGE 提供标准的 Cypher 布尔类型。布尔类型可以有几种状态:"true"、"false"和第三种状态"unknown",由 Agtype null 值表示。
布尔常量可以在 Cypher 查询中由关键字 TRUE、FALSE 和 NULL 表示。
输入/输出格式:
查询示例:
SELECT *
FROM cypher('graph_name', $$
RETURN TRUE
$$) AS (boolean_result agtype);与 Postgres 不同,AGE 的布尔输出为完整单词,即 true 和 false,而不是 t 和 f。
查询结果:
boolean_result |
true |
(1 row) |
Agtype 字符串字符串字面量可以包含以下转义序列:
转义序列 | 字符 |
| 制表符 |
| 退格 |
| 换行 |
| 回车 |
| 换页 |
| 单引号 |
| 双引号 |
| 反斜杠 |
| Unicode UTF-16 代码点(\u 后必须跟 4 个十六进制数字) |
输入/输出格式:
使用单引号(')来标识字符串。输出将使用双引号(")。
查询示例:
SELECT *
FROM cypher('graph_name', $$
RETURN 'This is a string'
$$) AS (string_result agtype);查询结果:
string_result |
"This is a string" |
(1 row) |
在 Cypher 中,列表(List) 是一种有序集合,用于存储一组元素。
列表可以包含任意类型的值(包括数字、字符串、布尔值、节点、边,甚至其他列表)。所有示例都将使用 WITH 子句和 RETURN 子句。
可以通过在方括号 [ ] 中以逗号分隔的方式创建字面量列表。
查询示例:
SELECT *
FROM cypher('graph_name', $$
WITH [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as lst
RETURN lst
$$) AS (lst agtype);查询结果:
lst |
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] |
(1 row) |
列表可以保存 null 值,与 null 是独立值不同,它将在列表中显示为单词 'null'。
查询示例:
SELECT *
FROM cypher('graph_name', $$
WITH [null] as lst
RETURN lst
$$) AS (lst agtype);查询结果:
lst |
[null] |
(1 row) |
要访问列表中的单个元素,我们再次使用方括号。这将从起始索引提取到但不包括结束索引。
查询示例:
SELECT *
FROM cypher('graph_name', $$
WITH [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as lst
RETURN lst[3]
$$) AS (element agtype);查询结果:
element |
3 |
(1 row) |
查询示例:
SELECT *
FROM cypher('graph_name', $$
WITH [0, {key: 'key_value'}, 2, 3, 4, 5, 6, 7, 8, 9, 10] as lst
RETURN lst
$$) AS (map_value agtype);查询结果:
map_value |
[0, {"key": "key_value"}, 2, 3, 4, 5, 6, 7, 8, 9, 10] |
(1 row) |
查询示例:
SELECT *
FROM cypher('graph_name', $$
WITH [0, {key: 'key_value'}, 2, 3, 4, 5, 6, 7, 8, 9, 10] as lst
RETURN lst[1].key
$$) AS (map_value agtype);查询结果:
map_value |
"key_value" |
(1 row) |
您也可以使用负数,从列表的末尾开始。
查询示例:
SELECT *
FROM cypher('graph_name', $$
WITH [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as lst
RETURN lst[-3]
$$) AS (element agtype);查询结果:
element |
8 |
(1 row) |
最后,您可以在方括号内使用范围来返回列表的范围。
查询示例:
SELECT *
FROM cypher('graph_name', $$
WITH [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as lst
RETURN lst[0..3]
$$) AS (element agtype);查询结果:
element |
[0, 1, 2] |
(1 row) |
查询示例:
SELECT *
FROM cypher('graph_name', $$
WITH [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as lst
RETURN lst[0..-5]
$$) AS (lst agtype);查询结果:
lst |
[0, 1, 2, 3, 4, 5] |
(1 row) |
查询示例:
SELECT *
FROM cypher('graph_name', $$
WITH [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as lst
RETURN lst[..4]
$$) AS (lst agtype);查询结果:
lst |
[0, 1, 2, 3] |
(1 row) |
查询示例:
SELECT *
FROM cypher('graph_name', $$
WITH [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as lst
RETURN lst[-5..]
$$) AS (lst agtype);查询结果:
lst |
[6, 7, 8, 9, 10] |
(1 row) |
越界切片会被简单截断,但越界的单个元素返回 null。
查询示例:
SELECT *
FROM cypher('graph_name', $$
WITH [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as lst
RETURN lst[15]
$$) AS (element agtype);查询结果:
element |
(1 row) |
查询示例:
SELECT *
FROM cypher('graph_name', $$
WITH [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as lst
RETURN lst[5..15]
$$) AS (element agtype);查询结果:
element |
[5, 6, 7, 8, 9, 10] |
(1 row) |
可以使用 Cypher 构建映射。
您可以使用简单的 agtype 构建简单映射。
查询示例:
SELECT *
FROM cypher('graph_name', $$
WITH {int_key: 1, float_key: 1.0, numeric_key: 1::numeric, bool_key: true, string_key: 'Value'} as m
RETURN m
$$) AS (m agtype);查询结果:
m |
{"int_key": 1, "bool_key": true, "float_key": 1.0, "string_key": "Value", "numeric_key": 1::numeric} |
(1 row) |
映射也可以包含复合数据类型,即列表和其他映射。
查询示例:
SELECT *
FROM cypher('graph_name', $$
WITH {listKey: [{inner: 'Map1'}, {inner: 'Map2'}], mapKey: {i: 0}} as m
RETURN m
$$) AS (m agtype);查询结果:
m |
{"mapKey": {"i": 0}, "listKey": [{"inner": "Map1"}, {"inner": "Map2"}]} |
(1 row) |
查询示例:
SELECT *
FROM cypher('graph_name', $$
WITH {int_key: 1, float_key: 1.0, numeric_key: 1::numeric, bool_key: true, string_key: 'Value'} as m
RETURN m.int_key
$$) AS (int_key agtype);查询结果:
int_key |
1 |
(1 row) |
查询示例:
SELECT *
FROM cypher('graph_name', $$
WITH {listKey: [{inner: 'Map1'}, {inner: 'Map2'}], mapKey: {i: 0}} as m
RETURN m.listKey[0]
$$) AS (m agtype);查询结果:
m |
{"inner": "Map1"} |
(1 row) |
实体具有唯一的、可比较的身份,它定义了两个实体是否相等。
实体被分配一组属性,每个属性在集合中由其各自的属性键唯一标识。
简单实体被分配一个唯一的 graphid。graphid 是实体标签 id 和分配给每个标签的唯一序列的唯一组合。请注意,在比较来自不同图的实体时,id 会有重叠。
标签是将顶点和边分类到某些类别的标识符。
边必须有标签,但顶点不需要。
顶点和边之间的标签名称不能重叠。
有关如何使用标签创建实体的信息,请参见 [CREATE] 子句。
顶点和边都可以有属性。属性是属性值,每个属性名称应该只定义为字符串类型。
顶点是图的基本实体,具有能够独立存在的独特属性。
顶点可以被分配标签。
顶点可以有零个或多个出边。
顶点可以有零个或多个入边。
数据格式:
属性名 | 描述 |
| 此顶点的 |
| 此顶点具有的标签名称。 |
| 与此顶点关联的属性。 |
{id:1; label: 'label_name'; properties: {prop1: value1, prop2: value2}}::vertex查询示例:
SELECT *
FROM cypher('graph_name', $$
WITH {id: 0, label: "label_name", properties: {i: 0}}::vertex as v
RETURN v
$$) AS (v agtype);查询结果:
v |
{"id": 0, "label": "label_name", "properties": {"i": 0}}::vertex |
(1 row) |
边是编码恰好两个节点(源节点和目标节点)之间有向连接的实体。出边是从其源节点的角度来看的有向关系。入边是从其目标节点的角度来看的有向关系。边被分配恰好一个边类型。
数据格式
属性名 | 描述 |
| 此边的 |
| 源节点的 |
| 目标节点的 |
| 此边具有的标签名称。 |
| 与此边关联的属性。 |
查询输出:
{id: 3; startid: 1; endid: 2; label: 'edge_label' properties{prop1: value1, prop2: value2}}::edge查询示例:
SELECT *
FROM cypher('graph_name', $$
WITH {id: 2, start_id: 0, end_id: 1, label: "label_name", properties: {i: 0}}::edge as e
RETURN e
$$) AS (e agtype);查询结果:
v |
{"id": 2, "label": "label_name", "end_id": 1, "start_id": 0, "properties": {"i": 0}}::edge |
(1 row) |
路径是一系列交替的顶点和边。路径必须以顶点开始,并且至少有一条边。
查询示例:
SELECT *
FROM cypher('graph_name', $$
WITH [{id: 0, label: "label_name_1", properties: {i: 0}}::vertex,
{id: 2, start_id: 0, end_id: 1, label: "edge_label", properties: {i: 0}}::edge,
{id: 1, label: "label_name_2", properties: {}}::vertex
]::path as p
RETURN p
$$) AS (p agtype);查询结果:
p |
(1 row) |
纯净模式