Source: https://dev-docs.nebula-graph.io/v5.3.2/database-gql-reference/variable-definition/agg/map_agg/ Documentation version: v5.3.2 # MapAgg A MapAgg aggregator value variable (`MapAgg`) 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 diagramsource 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](https://dev-docs.nebula-graph.io/v5.3.2/database-gql-reference/variable-definition/agg/#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`) | ✅ | ❌ | MapAgg aggregator value variable (`MapAgg`) | ✅ | ✅ ### Record as input For inputs of [records](https://dev-docs.nebula-graph.io/v5.3.2/database-gql-reference/data-types/record-type/), 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](https://dev-docs.nebula-graph.io/v5.3.2/database-gql-reference/variable-definition/agg/map_agg/#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` 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 -> LIST ```` 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`, 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`, it returns `0` of type `T`. - For `AvgAgg`, it returns `0.0` of double type. - For `MaxAgg`, it returns the minimum value that can be represented by type `T`. - For `MinAgg`, it returns the maximum value that can be represented by type `T`. - For `AndAgg`, it returns `true`. - For `OrAgg`, it returns `false`. - For `ListAgg`, it returns an empty list `[]`. - For `SetAgg`, it returns an empty list `[]`. - For `TopKAgg`, 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](https://dev-docs.nebula-graph.io/v5.3.2/database-gql-reference/ddl/graph-projection/create/). ### Global MapAgg aggregator value variables ```` ''' USE #movie_temporary_graph { VALUE global_map_1 MapAgg> // Map from INT keys to SUM of INT values VALUE global_map_2 MapAgg> 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> 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>` 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> VALUE global_agg MapAgg> 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 | ... ````