WITH

简介

使用 WITH,你可以在输出传递给后续查询部分之前对其进行操作。操作可以改变结果集中条目的形状和/或数量。

WITH 也可以像 RETURN 一样,使用别名将表达式引入结果中。

WITH 还用于将图的读取与图的更新分离。查询的每个部分必须是只读或只写的。从写入子句转到读取子句时,可以使用可选的 WITH 来实现。

在 YMatrix AGE 中,WITH 的场景主要有:

  • 中间处理(管道)
    WITH 相当于查询中间的一个"管道",把前面的结果处理一下再传给后面。 MATCH (p:Person) WITH p ORDER BY p.age DESC LIMIT 3 RETURN p.name, 先匹配所有 Person,用 WITH 按年龄排序取前 3 个,再返回名字。没有 WITH 的话,RETURN 只能一步到位,无法做这种中间筛选。

  • 别名(和 RETURN 类似) MATCH (p:Person) WITH p.name AS name, p.age AS age WHERE age > 30 RETURN name, WITH 把表达式重命名,后续子句用新名字引用。

  • 读写分离 Cypher 规定:一个查询片段要么只读,要么只写。CREATE 是写操作,MATCH/WHERE 是读操作。如果你想先写再读,必须用 WITH 隔开。 CREATE (a:Person {name: 'Tom'}) WITH a MATCH (a)-[:KNOWS]->(b) RETURN b, 没有中间的 WITH a,直接从 CREATE 跳到 MATCH 会报错,因为混合了读写。

  • 全局排序 在 YMatrix AGE 中,order by 不保证全局有序。因此 order by + limit 不保证取 全局有序的前三个。 如果需要保证全局有序,需要在ORDER BY 之前使用WITH 语句。

    1. RETURN p ORDER BY p.age LIMIT 3 → 每个 segment 各自排序取前 3,最终结果不一定是全局的前 3。
    2. WITH p ORDER BY p.age LIMIT 3 RETURN p → WITH 会触发数据汇聚(Motion 节点),在汇聚后做全局排序再取前 3。

过滤聚合函数结果

聚合结果必须通过 WITH 子句才能进行过滤。

查询

SELECT *
FROM cypher('graph_name', $$
        MATCH (david {name: 'David'})-[]-(otherPerson)-[]->()
        WITH otherPerson, count(*) AS foaf
        WHERE foaf > 1
        RETURN otherPerson.name
$$) as (name agtype);

查询将返回与 'David' 连接的、至少有一个以上出边关系的人的名字。

结果

| name     |
| -------- |
| "Anders" |
(1 row)    

在 collect 之前排序结果

你可以在将结果传递给 collect 之前对其排序,从而对生成的列表进行排序。

查询

SELECT *
FROM cypher('graph_name', $$
        MATCH (n) WITH n
        ORDER BY n.name DESC LIMIT 3
        RETURN collect(n.name)
$$) as (names agtype);

返回按名称逆序排列的人名列表,限制为 3 个,以列表形式返回。

结果

| names                     |
| ------------------------- |
| ["Emil","David","Ceasar"] |
 1 row                     

限制路径搜索的分支

你可以匹配路径,限制到一定数量,然后使用这些路径作为基础再次匹配,以及任意数量的类似限制搜索。

查询

SELECT *
FROM cypher('graph_name', $$
        MATCH (n {name: 'Anders'})-[]-(m) WITH m
        ORDER BY m.name DESC LIMIT 1
        MATCH (m)-[]-(o)
        RETURN o.name
$$) as (name agtype);

从 'Anders' 开始,找到所有匹配的节点,按名称降序排列并获取第一个结果,然后找到与该结果连接的所有节点,并返回它们的名称。

结果

| name      |
| --------- |
| "Anders"  |
| "Bossman" |
 (2 rows)