CALL 可以对每个子查询的结果进行独立的操作和运算,而非对整个查询结果进行运算。该子句将查询语句和运算子句包裹在大括号 {}
中,并在大括号内的一开始用 WITH 子句传入触发子查询的别名,在末尾用 RETURN 子句将子查询结果的运算后的别名传出。
语法:
call {
with <alias_In>
, <alias_In>
, ...
...
return <expression>
as <alias_Out>
, <expression>
as <alias_Out>
, ...
}
参数:
- <alias_In>:传入的别名
- <expression>:子查询结果运算后的返回值表达式
- <alias_Out>:子查询结果运算后的返回值别名,<expression> 为别名时 <alias_Out> 可省略
find().nodes([1, 5]) as nodes
call {
with nodes
n(nodes).e()[:2].n() as p
skip 1
return p as path
}
return path
上面 UQL 代码中,第一个子查询生成了 3 个p,第二个子查询生成了 2 个p,两个子查询的结果分别跳过了一行:
子查询内进行单次查询
示例:不使用 GROUP BY 子句,查询顾客 CU001、CU002、CU003 各自拥有多少张银行卡
uncollect ["CU001", "CU002", "CU003"] as user
call {
with user
n({_id == user}).e({@has}).n({@card} as n)
return count(n) as number
}
return user, number
解析:在 CALL 子句内,每个 user 的 n 分别进行聚合运算得到 number,相当于对所有 user 的 n 根据 user 分组并在组内进行聚合。
子查询内进行多次查询
示例:查找 10 笔转账金额大于 8,000 的边并为每一条边评分,如果边的起点、终点与银行卡 CA029 有过两步之内的转账行为,则为起点、终点加 0.5 分,起点、终点的得分总和即为该边的评分
n({@card} as n1).re({@transfer.amount > 8000} as e).n({@card} as n2).limit(10)
call {
with n1, n2
optional n(n1 as a1).e({@transfer})[:2].n({_id == "CA029"}).limit(1)
with CASE a1 when 0 then 0 else 0.5 END as c1
optional n(n2 as a2).e({@transfer})[:2].n({_id == "CA029"}).limit(1)
with CASE a2 when 0 then 0 else 0.5 END as c2
return c1+c2 as c
}
return e{*}, c
解析:n1、n2 分别为每条边 e 的起点和终点,CALL 子句对流入其内的每一条 e 的 n1、n2 都分别计算出分值 c1、c2,再求和为 c,c 即为每条 e 的总分值,其长度与 n1、n2、e 的长度相等。