MapAgg¶
MapAgg 聚合值变量(MapAgg<K, V>)是一组键值对的映射,其中每个键映射到一个聚合值。K表示键的数据类型,V表示嵌套的聚合器类型。
声明语法¶
- map_agg_declaration
- scalar_type
- key_type
- nested_aggregator
map_agg_declaration ::=
'NODE'? 'VALUE' aggregator_value_variable 'MapAgg' '<' key_type ',' nested_aggregator '>'
scalar_type ::= 'INT8'|'INT16'|'INT32'|'INT64'|'FLOAT'|'DOUBLE'|'STRING'
key_type ::= scalar_type
nested_aggregator ::=
'SumAgg' '<' scalar_type '>'
| 'AvgAgg' '<' ('INT64'|'FLOAT'|'DOUBLE') '>'
| 'MaxAgg' '<' scalar_type '>'
| 'MinAgg' '<' scalar_type '>'
| 'AndAgg'
| 'OrAgg'
| 'ListAgg' '<' ('INT8'|'INT16'|'INT32'|'INT64'|'FLOAT'|'DOUBLE'|'STRING'|'LIST'|'RECORD') '>'
| 'SetAgg' '<' scalar_type '>'
| 'TopKAgg' '<' 'RECORD' '>'
关于声明语法中参数的详细信息,请参见参数。
初始值¶
从声明语法中可见,声明时不能指定初始值。
输入类型与支持的操作¶
下表总结了 MapAgg 聚合值变量支持的输入类型以及对应的操作:
| 输入类型 | 赋值 | 聚合 |
|---|---|---|
记录(RECORD) |
❌ | ✅ |
记录列表(LIST<RECORD>) |
✅ | ❌ |
MapAgg 聚合值变量(MapAgg<K, V>) |
✅ | ✅ |
记录作为输入¶
对于记录这类输入,仅支持聚合操作。
此时,该记录必须有且仅有两个名为_0和_1的字段,其中_0对应键,_1对应值。键的数据类型必须为K,而值将使用嵌套的聚合器类型V进行聚合。
譬如,输入可以是RECORD{_0: key, _1: value},其简写形式为TUPLE(key, value)。两种形式可以互换使用。
对于每个TUPLE(key, value)形式的输入,聚合操作的行为如下:
- 若键在映射中不存在,则将键值对添加到映射中。
- 若键已存在于映射中,则使用嵌套的聚合器类型
V对其值进行聚合。
记录列表作为输入¶
对于记录构成的列表这类输入,仅支持赋值操作。
此时,列表中的每个记录必须有且仅有两个名为_0和_1的字段,相关约束如记录作为输入中所述。
譬如,输入可以是LIST[RECORD{_0: key1, _1: value1}, RECORD{_0: key2, _1: value2}],其简写形式为LIST[TUPLE(key1, value1), TUPLE(key2, value2)]。两种形式可以互换使用。
赋值操作会将目标映射中的键值对替换为列表中的记录所包含的键值对。
MapAgg<K, V>作为输入¶
对于声明类型相同的 MapAgg 聚合值变量这类输入,支持赋值和聚合操作。
- 赋值操作会将目标映射中的键值对替换为源映射中的键值对。
- 聚合操作会将源映射中的键值对合并到目标映射中。若目标映射中已存在源映射中的某个键,则会使用嵌套的聚合器类型
V对其值进行聚合。
返回类型¶
MapAgg<K, V> -> LIST<RECORD{_0: key, _1: aggregated_value}>
返回类型为一组记录组成的列表,其中每条记录的字段_0代表键,字段_1代表聚合后的值。
键的数据类型与声明时指定的类型K相同。
聚合后的值的类型与声明时指定的嵌套聚合器类型V的返回类型相同。例如,如果V声明为SumAgg<INT>,则聚合后的值的类型为INT。有关嵌套聚合器的返回类型,请参阅相应的聚合器文档。
成员函数¶
本节介绍 MapAgg 聚合值变量支持的成员函数。
size()¶
返回 MapAgg 聚合值变量中键值对的数量。
函数签名¶
size() -> UINT64
clear()¶
移除 MapAgg 聚合值变量中的所有键值对。
函数签名¶
clear() -> VOID
get()¶
返回指定键的聚合值。如果键不存在,则返回聚合值变量默认的空值,如下所示:
- 对于
SumAgg<T>,返回值为类型T的0。 - 对于
AvgAgg<T>,返回值为DOUBLE类型的0.0。 - 对于
MaxAgg<T>,返回值为类型T的最小值。 - 对于
MinAgg<T>,返回值为类型T的最大值。 - 对于
AndAgg,返回值为true。 - 对于
OrAgg,返回值为false。 - 对于
ListAgg<T>,返回值为空列表[]。 - 对于
SetAgg<T>,返回值为空列表[]。 - 对于
TopKAgg<T>,返回值为空列表[]。
函数签名¶
get(key: K) -> aggregated_value
contains_key()¶
若指定的键在 MapAgg 聚合值变量中存在,则返回true,否则返回false。
函数签名¶
contains_key(key: K) -> BOOL
示例¶
以下示例基于 CREATE TEMPORARY GRAPH 中创建的临时图#movie_temporary_graph。
全局 MapAgg 聚合值变量¶
'''
USE #movie_temporary_graph {
VALUE global_map_1 MapAgg<INT, SumAgg<INT>> // 将 INT 类型的键映射到 INT 类型的求和聚合器
VALUE global_map_2 MapAgg<INT, SumAgg<INT>>
SET @global_map_1 += TUPLE(1, 10) // map: {1: 10}
SET @global_map_1 += TUPLE(2, 20) // map: {1: 10, 2: 20}
SET @global_map_1 += TUPLE(1, 5) // map: {1: 15, 2: 20} (相同的键 1 对应的值被求和)
SET @global_map_1 += TUPLE(3, 30) // map: {1: 15, 2: 20, 3: 30}
LOG_INFO("@global_map_1: ", @global_map_1)
// 用空列表进行赋值
SET @global_map_1 = LIST[] // 清空映射
LOG_INFO("Map from empty LIST:", @global_map_1) // 输出:[]
// 用一组记录的列表进行赋值
SET @global_map_1 = LIST[TUPLE(1, 2), TUPLE(3, 3), TUPLE(2, 1)] // 创建映射: {1: 2, 2: 1, 3: 3}
LOG_INFO("Map from LIST assignment: ", @global_map_1)
SET @global_map_2 += TUPLE(1, 5)
SET @global_map_2 += TUPLE(2, 10)
SET @global_map_2 += TUPLE(1, 3) // global_map_2: {1: 8, 2: 10}
LOG_INFO("@global_map_2: ", @global_map_2)
// 用另一个 MapAgg 进行赋值
SET @global_map_1 = @global_map_2 // 将 global_map_2 赋值给 global_map_1
LOG_INFO("Map after assignment: ", @global_map_1) // map: {1: 8, 2: 10}
// 用另一个 MapAgg 进行聚合
SET @global_map_1 += @global_map_2 // 将 global_map_2 合并到 global_map_1
LOG_INFO("Map after aggregation: ", @global_map_1) // map: {1: 16, 2: 20}
// 成员函数
SET @global_map_2.clear() // 清空映射
LOG_INFO("Clear the map:", @global_map_2) // 输出:[]
LOG_INFO("Size: ", @global_map_1.size()) // 输出: 2
LOG_INFO("Value for key 1: ", @global_map_1.get(1)) // 输出: 16
LOG_INFO("Value for key 100: ", @global_map_1.get(100)) // 输出: 0
LOG_INFO("Contains key 2: ", @global_map_1.contains_key(2)) // 输出: true
LOG_INFO("Contains key 100: ", @global_map_1.contains_key(100)) // 输出: false
}
'''
返回:
Log:
2025-08-18T07:21:45.182062 INFO - @global_map_1: [{_0:3,_1:30},{_0:2,_1:20},{_0:1,_1:15}]
2025-08-18T07:21:45.182653 INFO - Map from empty LIST:[]
2025-08-18T07:21:45.182980 INFO - Map from LIST assignment: [{_0:2,_1:1},{_0:3,_1:3},{_0:1,_1:2}]
2025-08-18T07:21:45.183698 INFO - @global_map_2: [{_0:2,_1:10},{_0:1,_1:8}]
2025-08-18T07:21:45.184218 INFO - Map after assignment: [{_0:1,_1:8},{_0:2,_1:10}]
2025-08-18T07:21:45.184541 INFO - Map after aggregation: [{_0:1,_1:16},{_0:2,_1:20}]
2025-08-18T07:21:45.184812 INFO - Clear the map:[]
2025-08-18T07:21:45.184950 INFO - Size: 2
2025-08-18T07:21:45.185127 INFO - Value for key 1: 16
2025-08-18T07:21:45.185312 INFO - Value for key 100: 0
2025-08-18T07:21:45.185462 INFO - Contains key 2: true
2025-08-18T07:21:45.185653 INFO - Contains key 100: false
点绑定 MapAgg 聚合值变量¶
'''
USE #movie_temporary_graph {
NODE VALUE node_map MapAgg<DOUBLE, ListAgg<INT>>
MATCH (a@User WHERE a.id IN [1,3,4])-[w@Watch]->(b@Movie)
PER PATH {
// 对于每条匹配的路径,将评分作为键,将电影 ID 作为值添加到用户的映射中
SET a.@node_map += TUPLE(w.rate, b.id)
}
PER NODE (a) {
LOG_INFO("a.id: ", a.id, " a.@node_map: ", a.@node_map)
}
}
'''
上述示例声明了一个类型为MapAgg<DOUBLE, ListAgg<INT>>的点绑定聚合值变量node_map。该变量将电影评分(类型为DOUBLE)映射到特定用户的电影 ID 列表(类型为INT)。
返回:
Log:
2025-08-12T02:06:27.859707 INFO - a.id: 4 a.@node_map: [{_0:1,_1:[10,637,144,11,473]},{_0:2,_1:[346]},{_0:5,_1:[104,99]},{_0:4,_1:[252,146,671]},{_0:3,_1:[648]}]
2025-08-12T02:06:27.859707 INFO - a.id: 1 a.@node_map: [{_0:5,_1:[601,100,497,651,104,252,473]},{_0:4,_1:[10,11]}]
2025-08-12T02:06:27.859707 INFO - a.id: 3 a.@node_map: [{_0:3,_1:[152]},{_0:4.5,_1:[473]}]
全局和点绑定 MapAgg 聚合值变量组合使用¶
"""
USE #movie_temporary_graph {
NODE VALUE map_agg MapAgg<STRING,SumAgg<INT>>
VALUE global_agg MapAgg<STRING,SumAgg<INT>>
MATCH (a@Actor)
PER NODE (a) {
SET a.@map_agg += TUPLE(CAST (a.birthDate AS STRING), 1)
SET @global_agg += a.@map_agg
}
FOR r IN @global_agg
RETURN r._0 as key , r._1 as val
}
"""
上述示例使用点绑定聚合值变量map_agg统计每个出生日期的演员数量,然后将这些数量聚合到全局聚合值变量global_agg中。
返回:
+------------+-----+
| key | val |
+------------+-----+
| 1932-02-06 | 1 |
| 1962-06-27 | 1 |
| 1988-12-10 | 1 |
| 1964-08-14 | 1 |
| 1954-04-16 | 1 |
| 1944-01-22 | 1 |
| 1924-08-25 | 1 |
| 1950-06-03 | 1 |
| 1932-02-23 | 1 |
| 1961-12-16 | 3 |
| 1975-02-22 | 2 |
...