跳转至
开发版采用单机部署,无需产品 License 文件。需要多机部署或大规模性能测试? 了解企业版

TopKAgg

TopKAgg 聚合值变量(TopKAgg<K, SortFields>)根据指定的排序字段(SortFields)维护前 K 条记录。该变量自动保留根据排序规则(升序或降序)排序后的前 K 条记录,并在记录数量超过 K 时丢弃其他记录。

声明语法

topk_agg_declaration
NODE VALUE aggregator_value_variable TopKAgg < top_k , sort_field data_type ASC ASCENDING DESC DESCENDING NULLS FIRST NULLS LAST , >

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 聚合器值变量的具体参数。关于声明语法中其他参数的详细信息,请参见参数。

top_k

要保留的记录的最大数量。该值必须为大于 0 的整数。

sort_field

用于排序的字段。输入中的字段必须与该字段相匹配。

data_type

排序字段的数据类型。支持排序的数据类型有:

ASC | ASCENDING | DESC | DESCENDING

排序规则:

  • ASC/ASCENDING:默认值,按升序排序值。
  • DESC/DESCENDING:按降序排序值。

如果有多个排序字段,记录先按照第一个排序字段进行排序。如果第一个排序字段的取值相同,则按照第二个排序字段对记录进行排序,以此类推。

关于每种数据类型的值的比较规则,请参见 comp_op。

NULLS FIRST | NULLS LAST

排序结果中null值的位置。

  • NULLS FIRST:null值排在排序结果的开头。当排序规则为DESC或DESCENDING时,这是默认行为。
  • NULLS LAST:null值排在排序结果的末尾。当排序规则为ASC或ASCENDING时,这是默认行为。

初始值

从声明语法中可见,声明时不能指定初始值。

输入类型与支持的操作

下表总结了 TopKAgg 聚合值变量支持的输入类型以及对应的操作:

输入类型 赋值 聚合
记录(RECORD) ❌ ✅
记录列表(LIST<RECORD>) ✅ ❌
TopKAgg 聚合值变量(TopKAgg<K, SortFields>) ✅ ✅

TopKAgg 聚合值变量支持聚合(+=)和赋值(=)操作。

  • 赋值操作(=):右侧输入须为记录列表或 TopKAgg 聚合值变量。
    • 若输入为记录列表,则赋值操作使用列表中的记录替换目标变量中的内容。记录的字段需与声明时的排序字段一致,替换后仅保留按排序规则确定的前 K 条记录。
    • 若输入为同类型的 TopKAgg 聚合值变量,则赋值操作拷贝变量中的记录并替换目标变量内容,结果中仅保留排序后的前 K 条记录。
  • 聚合操作(+=):右侧输入须为记录或 TopKAgg 聚合值变量。
    • 若输入为单条记录,则聚合操作将其添加至目标变量中,该记录的字段需匹配排序字段,合并后仅保留排序后的前 K 条记录。
    • 若输入为同类型的 TopKAgg 聚合值变量,则聚合操作将其中所有记录合并到目标变量中,最终仅保留按排序规则排序的前 K 条记录。

返回类型

TopKAgg<K, SortFields> -> LIST<RECORD>

返回类型为一组根据排序规则排序后的由前 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 中创建的临时图#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}]