Source: https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/variable-definition/agg/topk_agg/ Documentation version: v5.3.2 # TopKAgg TopKAgg 聚合值变量(`TopKAgg`)根据指定的排序字段(`SortFields`)维护前 K 条记录。该变量自动保留根据排序规则(升序或降序)排序后的前 K 条记录,并在记录数量超过 K 时丢弃其他记录。 ## 声明语法 语法图源码 topk_agg_declaration ```` topk_agg_declaration ::= 'NODE'? 'VALUE' aggregator_value_variable 'TopKAgg' '<' top_k ',' (sort_field data_type ( 'ASC' | 'ASCENDING' | 'DESC' | 'DESCENDING' )? ('NULLS FIRST' | 'NULLS LAST')? ) (',' (sort_field data_type ( 'ASC' | 'ASCENDING' | 'DESC' | 'DESCENDING' )? ('NULLS FIRST' | 'NULLS LAST')? ))* '>' ```` ## 参数 以下是 TopKAgg 聚合器值变量的具体参数。关于声明语法中其他参数的详细信息,请参见[参数](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/variable-definition/agg/#_6)。 ### `top_k` 要保留的记录的最大数量。该值必须为大于 0 的整数。 ### `sort_field` 用于排序的字段。输入中的字段必须与该字段相匹配。 ### `data_type` 排序字段的数据类型。支持排序的数据类型有: - [数值](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/data-types/numeric-type/) - [字符串](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/data-types/c-string-type/) - [布尔](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/data-types/boolean-type/) - [日期和时间](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/data-types/temporal-type/) ### `ASC | ASCENDING | DESC | DESCENDING` 排序规则: - `ASC`/`ASCENDING`:默认值,按升序排序值。 - `DESC`/`DESCENDING`:按降序排序值。 如果有多个排序字段,记录先按照第一个排序字段进行排序。如果第一个排序字段的取值相同,则按照第二个排序字段对记录进行排序,以此类推。 关于每种数据类型的值的比较规则,请参见 [comp_op](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/fe/predicates/comparison/#comp_op)。 ### `NULLS FIRST | NULLS LAST` 排序结果中`null`值的位置。 - `NULLS FIRST`:`null`值排在排序结果的开头。当排序规则为`DESC`或`DESCENDING`时,这是默认行为。 - `NULLS LAST`:`null`值排在排序结果的末尾。当排序规则为`ASC`或`ASCENDING`时,这是默认行为。 ## 初始值 从声明语法中可见,声明时不能指定初始值。 ## 输入类型与支持的操作 下表总结了 TopKAgg 聚合值变量支持的输入类型以及对应的操作: | 输入类型 | 赋值 | 聚合 | 记录(`RECORD`) | ❌ | ✅ | 记录列表(`LIST`) | ✅ | ❌ | TopKAgg 聚合值变量(`TopKAgg`) | ✅ | ✅ TopKAgg 聚合值变量支持聚合(`+=`)和赋值(`=`)操作。 - 赋值操作(`=`):右侧输入须为[记录列表](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/data-types/list-type/)或 TopKAgg 聚合值变量。 - 若输入为记录列表,则赋值操作使用列表中的记录替换目标变量中的内容。记录的字段需与声明时的排序字段一致,替换后仅保留按排序规则确定的前 K 条记录。 - 若输入为同类型的 TopKAgg 聚合值变量,则赋值操作拷贝变量中的记录并替换目标变量内容,结果中仅保留排序后的前 K 条记录。 - 聚合操作(`+=`):右侧输入须为[记录](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/data-types/record-type/)或 TopKAgg 聚合值变量。 - 若输入为单条记录,则聚合操作将其添加至目标变量中,该记录的字段需匹配排序字段,合并后仅保留排序后的前 K 条记录。 - 若输入为同类型的 TopKAgg 聚合值变量,则聚合操作将其中所有记录合并到目标变量中,最终仅保留按排序规则排序的前 K 条记录。 ## 返回类型 ```` TopKAgg -> LIST ```` 返回类型为一组根据排序规则排序后的由前 K 条记录组成的列表。 ## 成员函数 本节介绍 TopKAgg 聚合值变量支持的成员函数。 ### size() 返回 TopKAgg 聚合值变量中记录的数量。 #### 函数签名 ```` size() -> UINT64 ```` ### clear() 清空 TopKAgg 聚合值变量中的所有记录。 #### 函数签名 ```` clear() -> VOID ```` ### min() 返回 TopKAgg 聚合值变量中根据排序规则排序后的最后一个记录。例如,如果列表记录`[RECORD{test:1}, RECORD{test:2}, RECORD{test:3}]`按照`test`字段升序排序,则`min()`返回最后一条记录`RECORD{test:3}`。 #### 函数签名 ```` min() -> RECORD ```` ## 示例 以下示例基于 [CREATE TEMPORARY GRAPH](https://dev-docs.yueshu.com.cn/v5.3.2/database-gql-reference/ddl/graph-projection/create/) 中创建的临时图`#movie_temporary_graph`。 ### 全局 TopKAgg 聚合值变量 ```` ''' USE #movie_temporary_graph { VALUE global_topk TopKAgg<3, test INT ASC> // 定义一个 TopK 聚合值变量,保留最小的 3 个 test 值的记录 VALUE global_topk2 TopKAgg<2, test INT DESC> // 定义另一个同类型 TopKAgg 聚合值变量,保留最大的 2 个 test 值的记录 SET @global_topk += RECORD{test:1} // topk: [RECORD{test:1}] SET @global_topk += RECORD{test:3} // topk: [RECORD{test:1}, RECORD{test:3}] SET @global_topk += RECORD{test:4} // topk: [RECORD{test:1}, RECORD{test:3}, RECORD{test:4}] SET @global_topk += RECORD{test:2} // topk: [RECORD{test:1}, RECORD{test:2}, RECORD{test:3}] (4 被丢弃) SET @global_topk += RECORD{test:-1} // topk: [RECORD{test:-1}, RECORD{test:1}, RECORD{test:2}] (3 被丢弃) LOG_INFO("@global_topk: ", @global_topk) SET @global_topk2 += RECORD{test:10} SET @global_topk2 += RECORD{test:5} SET @global_topk2 += RECORD{test:15} LOG_INFO("@global_topk2: ", @global_topk2) // 从记录列表赋值 // 将保留最小的 3 个: [RECORD{test:3}, RECORD{test:5}, RECORD{test:8}] SET @global_topk = LIST[RECORD{test:10}, RECORD{test:5}, RECORD{test:15}, RECORD{test:8}, RECORD{test:3}] LOG_INFO("TopK from LIST assignment: ", @global_topk) // 从空记录列表赋值 SET @global_topk = [] LOG_INFO("TopK from empty LIST: ", @global_topk) // 输出: [] // 将 global_topk2 赋值给 global_topk SET @global_topk = @global_topk2 LOG_INFO("TopK from global_topk2: ", @global_topk) // 输出: [RECORD{test:10}, RECORD{test:15}] // 成员函数 LOG_INFO("Size: ", @global_topk.size()) // 查看记录数量 LOG_INFO("Min: ", @global_topk.min()) // 查看排序列表中的最后一个记录。 SET @global_topk.clear() // 清空 TopK 聚合值变量 LOG_INFO("Clear the TopK aggregator: ", @global_topk) } ''' ```` 返回: ```` Log: 2025-08-22T11:31:41.456183 INFO - @global_topk: [{test:-1},{test:1},{test:2}] 2025-08-22T11:31:41.457019 INFO - @global_topk2: [{test:15},{test:10}] 2025-08-22T11:31:41.457372 INFO - TopK from LIST assignment: [{test:3},{test:5},{test:8}] 2025-08-22T11:31:41.457667 INFO - TopK from empty LIST: [] 2025-08-22T11:31:41.457955 INFO - TopK from global_topk2: [{test:10},{test:15}] 2025-08-22T11:31:41.458123 INFO - Size: 2 2025-08-22T11:31:41.458309 INFO - Min: {test:15} 2025-08-22T11:31:41.458631 INFO - Clear the TopK aggregator: [] ```` ### 点绑定 TopKAgg 聚合值变量 ```` ''' USE #movie_temporary_graph { // 为每个点定义一个 TopK 聚合器,保留前 2 条记录 // 首先按评分降序排序,如果评分相同则按邻居 ID 降序排序 NODE VALUE node_topk TopKAgg<2, score DOUBLE DESC, neigh_id INT DESC> // 匹配从用户点(ID 为 1、3、4)通过观看关系指向电影点的路径 MATCH (a@User WHERE a.id IN [1,3,4])-[w@Watch]->(b@Movie) PER PATH { // 对于每条匹配的路径,将包含评分和电影 ID 的记录添加到用户的 TopK 聚合值变量中 SET a.@node_topk += RECORD{score: w.rate, neigh_id: b.id} } PER NODE (a) { LOG_INFO("a.id: ", a.id, " a.@node_topk: ", a.@node_topk) } } ''' ```` 返回: ```` Log: 2025-08-23T08:23:53.020313 INFO - a.id: 4 a.@node_topk: [{neigh_id:104,score:5},{neigh_id:99,score:5}] 2025-08-23T08:23:53.020313 INFO - a.id: 3 a.@node_topk: [{neigh_id:473,score:4.5},{neigh_id:152,score:3}] 2025-08-23T08:23:53.020313 INFO - a.id: 1 a.@node_topk: [{neigh_id:651,score:5},{neigh_id:601,score:5}] ````