MapAgg¶
A MapAgg aggregator value variable (MapAgg<K, V>) maintains a map of key-value pairs where each key maps to an aggregated value. K represents the data type of the key, and V represents the nested aggregator type.
Declaration syntax¶
- 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' '>'
For information about the parameters in the declaration syntax, see Parameters.
Initial value¶
As indicated in the declaration syntax, an initial value must not be specified during declaration.
Input type and supported operations¶
The following table summarizes the input types and the corresponding operations supported by MapAgg aggregator value variables:
| Input type | Assignment | Aggregation |
|---|---|---|
Record (RECORD) |
❌ | ✅ |
Record list (LIST<RECORD>) |
✅ | ❌ |
MapAgg aggregator value variable (MapAgg<K, V>) |
✅ | ✅ |
Record as input¶
For inputs of records, only aggregation operations are supported.
In this case, the record must have two and only two fields named _0 and _1, where _0 corresponds to the key and _1 corresponds to the value. The key must be of data type K, and the value is to be aggregated using the nested aggregator type V.
A sample input is RECORD{_0: key, _1: value}, which can also be written as TUPLE(key, value) for brevity. Both forms can be used interchangeably.
For each input of the form TUPLE(key, value), the aggregation operation behaves as follows:
- If the key does not already exist in the map, the key-value pair is added to the map.
- If the key already exists in the map, its value is aggregated using the nested aggregator type
V.
List of records as input¶
For inputs of lists of records, only assignment operations are supported.
In this case, each record in the list must have two and only two fields named _0 and _1 as described in the section Record as input.
A sample input is LIST[RECORD{_0: key1, _1: value1}, RECORD{_0: key2, _1: value2}], which can also be written as LIST[TUPLE(key1, value1), TUPLE(key2, value2)] for brevity. Both forms can be used interchangeably.
The assignment operation replaces the key-value pairs in the target map with those from the list of records.
MapAgg<K, V> as input¶
For inputs of MapAgg aggregator value variables with the same declaration type, both assignment and aggregation operations are supported.
- The assignment operation replaces the key-value pairs in the target map with those from the source map.
- The aggregation operation merges the key-value pairs from the source map into the target map, aggregating values for the same keys using the nested aggregator type
V.
Return type¶
MapAgg<K, V> -> LIST<RECORD{_0: key, _1: aggregated_value}>
The return type is a list of records, where each record contains the key in field _0 and the aggregated value in field _1.
The data type of the key is K, which is specified during declaration.
The data type of the aggregated value is the return type of the nested aggregator type V, which is also specified during declaration. For example, if V is declared as SumAgg<INT>, then the aggregated value is of type INT. For more information about the return type of the nested aggregator, see the corresponding aggregator documentation.
Member functions¶
This section introduces the member functions supported by MapAgg aggregator value variables.
size()¶
Returns the number of key-value pairs held by a MapAgg aggregator value variable.
Function signature¶
size() -> UINT64
clear()¶
Removes all key-value pairs held by a MapAgg aggregator value variable.
Function signature¶
clear() -> VOID
get()¶
Returns the aggregated value for the specified key. If the key does not exist, it returns the default empty value of the aggregator value variable as follows:
- For
SumAgg<T>, it returns0of typeT. - For
AvgAgg<T>, it returns0.0of double type. - For
MaxAgg<T>, it returns the minimum value that can be represented by typeT. - For
MinAgg<T>, it returns the maximum value that can be represented by typeT. - For
AndAgg, it returnstrue. - For
OrAgg, it returnsfalse. - For
ListAgg<T>, it returns an empty list[]. - For
SetAgg<T>, it returns an empty list[]. - For
TopKAgg<T>, it returns an empty list[].
Function signature¶
get(key: K) -> aggregated_value
contains_key()¶
Returns true if the specified key exists in a MapAgg aggregator value variable; otherwise, it returns false.
Function signature¶
contains_key(key: K) -> BOOL
Examples¶
The following examples are based on the temporary graph #movie_temporary_graph created in CREATE TEMPORARY GRAPH.
Global MapAgg aggregator value variables¶
'''
USE #movie_temporary_graph {
VALUE global_map_1 MapAgg<INT, SumAgg<INT>> // Map from INT keys to SUM of INT values
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} (values for key 1 are summed)
SET @global_map_1 += TUPLE(3, 30) // map: {1: 15, 2: 20, 3: 30}
LOG_INFO("@global_map_1: ", @global_map_1)
// Assignment from empty LIST
SET @global_map_1 = LIST[] // Clear the map
LOG_INFO("Map from empty LIST:", @global_map_1) // output: []
// Assignment from a LIST of RECORDs
SET @global_map_1 = LIST[TUPLE(1, 2), TUPLE(3, 3), TUPLE(2, 1)] // create map: {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)
// Assignment from another MapAgg
SET @global_map_1 = @global_map_2 // Assign global_map_2 to global_map_1
LOG_INFO("Map after assignment: ", @global_map_1) // map: {1: 8, 2: 10}
// Aggregation from another MapAgg
SET @global_map_1 += @global_map_2 // Merging global_map_2 into global_map_1
LOG_INFO("Map after aggregation: ", @global_map_1) // map: {1: 16, 2: 20}
// Member functions
SET @global_map_2.clear() // Clear the map
LOG_INFO("Clear the map:", @global_map_2) // output: []
LOG_INFO("Size: ", @global_map_1.size()) // output: 2
LOG_INFO("Value for key 1: ", @global_map_1.get(1)) // output: 16
LOG_INFO("Value for key 100: ", @global_map_1.get(100)) // output: 0
LOG_INFO("Contains key 2: ", @global_map_1.contains_key(2)) // output: true
LOG_INFO("Contains key 100: ", @global_map_1.contains_key(100)) // output: false
}
'''
Return:
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
Node-attached MapAgg aggregator value variables¶
'''
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 {
// For each matched path, add the rating as key and movie ID as value to the user's map
SET a.@node_map += TUPLE(w.rate, b.id)
}
PER NODE (a) {
LOG_INFO("a.id: ", a.id, " a.@node_map: ", a.@node_map)
}
}
'''
In the preceding example, a node-attached aggregator value variable node_map of type MapAgg<DOUBLE, ListAgg<INT>> is declared. This variable maps movie ratings (of type DOUBLE) to a list of movie IDs (of type INT) for specific users.
Return:
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]}]
Global and node-attached MapAgg aggregator value variables used together¶
"""
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
}
"""
The preceding example uses the node-attached MapAgg aggregator value variable map_agg to count the number of actors born on each day, and then aggregates these counts into the global MapAgg aggregator value variable global_agg.
Return:
+------------+-----+
| 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 |
...