数据流
数据流是指 UQL 运行时迭代产生的一行一行数据,这些数据被赋予别名之后,像水流一样从较早的链式语句、子句中流出,再一行行流入下一个链式语句、子句。在本章的语境中别名等同于数据流,数据流中的数据同样有 6 种结构:NODE、EDGE、PATH、ATTR、ARRAY、TABLE,见《查询》-《别名系统》。
同源别名
从同一个查询结果输出或计算得出的多个别名称为同源别名。同源别名的数据行数是相等的,各别名在同一行中的数据有对应关系。
下图中的模板查询语句查到了 5 条路径 path,path 的终点 tail、路径长度 length 这两个别名和 path 是同源的,也都含有 5 行数据,且每行中的 tail 和 length 代表该行中 path 的终点和路径长度:
对别名进行聚合、去重及各种子句操作(在 RETURN 子句中进行的去重操作除外)时,其同源别名中相对应的数据行也被同步舍弃或调整顺序;在 RETURN 子句中对别名进行去重操作时,其同源别名的各行保持不变。下图中的(a)、(b)分别展示了这两种情况。
异源别名
从毫无关联的两个或更多查询结果输出或计算得出的别名是异源别名,即非同源的。异源别名的数据行数通常不相同,行内各别名的数据之间也没有对应关系。
下图中的两个 UNCOLLECT 子句分别产生的别名 a,b 不同源,数据行数分别为 3 和 2:
异源别名作为输入同时进入到链式语句、子句、函数中时,会分情况进行处理:
- 进入 RETURN 子句且不进行数值、函数等运算时:直接返回,不进行处理(如上图所示)
- 进入某个 WITH 子句且不进行聚合运算时:不同源的别名之间按行做笛卡尔乘积
- 其余情况时:按照最小的数据行数进行裁剪后再查询或运算
下图中的(a)、(b)分别展示了上述 2、3 两种情况。
无论何种情况,异源别名在共同完成了 UQL 的某一步之后,均变为同源别名。
别名触发的子查询
当别名作为链式语句的输入时,该语句执行的次数就是别名中数据的行数,每次执行使用别名中的一行数据(系统会根据实际情况进行优化)。
下图中的 K 邻查询语句找到了 4 个 n,其后的点删除语句以 n 为输入共执行了 4 次,每次删除一个点:
如果别名进入的链式语句是一个查询语句,则称该语句的每一次执行为一个子查询,由于每个子查询都可能产生多行数据,最终产生的所有数据的行数就等于其每个子查询所产生的数据行数的总和。
下图中的 UQL 语句先产生了红、蓝两个节点 n,其后的点查询语句以 n 为输入共执行了 2 次子查询,第一次查到三个红色节点,第二次查到两个蓝色节点,总的 result 共 5 个:
子查询结果的处理
UQL 的聚合类函数、去重函数、以及本章所介绍的子句(除 CALL 以外)都是将别名中所有行作为整体进行相应的操作和运算。如果希望对别名中由每个子查询分别所产生的结果进行聚合、去重、子句等操作,这时需要使用子查询 CALL 子句来进行处理,详见本章后面的《CALL》中的介绍。除此之外,在《查询》中介绍过的参数 limit(<N>)
、查询前缀 OPTIONAL 也都是针对子查询的结果进行判断和处理的。下图中的(a)、(b)分别以 limit(<N>)
和 LIMIT 为例展示了对子查询的结果进行限长、和对整个查询的结果进行限长的区别。