Skip to content
Developer Edition runs on one host and does not require a product license file. Need multi-host deployment or performance testing at scale? Explore Enterprise Edition

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
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 >

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 returns 0 of type T.
  • For AvgAgg<T>, it returns 0.0 of double type.
  • For MaxAgg<T>, it returns the minimum value that can be represented by type T.
  • For MinAgg<T>, it returns the maximum value that can be represented by type T.
  • For AndAgg, it returns true.
  • For OrAgg, it returns false.
  • 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   |
...