求教一条MATCH和GO的管道混合写法.

提问参考模版:

  • nebula 版本:2.0.1
  • 部署方式(分布式 / 单机 / Docker / DBaaS):单机
  • 是否为线上版本:N
  • 硬件信息
    • 磁盘( 推荐使用 SSD):SSD
    • CPU、内存信息:略
  • 问题的具体描述:见正文
  • 相关的 meta / storage / graph info 日志信息:默认(未修改)

我的数据集合是这样的:

create tag class(name string);
create tag field(name string, type string);
create edge subclassOf();
create edge supperclassOf();
create edge fieldOf();
create edge hasField();

insert vertex class(name) values "A":("A"),"B":("B"),"C":("c");

insert vertex field(name, type) values "a1":("a1","string"),"a2":("a2","string"),"a3":("a3","string"),"b1":("b1","string"),"b2":("b2","string"),"c1":("c1","string"),"c2":("c2","string");

insert edge subclassOf() values "B"->"A":(),"C"->"B":();
insert edge supperclassOf() values "A"->"B":(),"B"->"C":();

insert edge fieldOf() values "a1"->"A":(),"a2"->"A":(),"a3"->"A":(),"b1"->"B":(),"b2"->"B":(),"c1"->"C":(),"c2"->"C":();
insert edge hasField() values "A"->"a1":(),"A"->"a2":(),"A"->"a3":(),"B"->"b1":(),"B"->"b2":(),"C"->"c1":(),"C"->"c2":();

可视化展示出来

我现在想查询,以及通过边subclassOf的0到n跳到达的所有其他节点.在这里的结果就是A,B,C.最终再通过hasField查询A,B,C的所有field.最终结果在这个数据集里是a1,a2,a3,b1,b2,c1,c2
(1)查询,以及通过边subclassOf的0到n跳到达的所有其他节点
MATCH p=(v)-[:subclassOf*..10]->(s) WHERE id(v) == 'C' UNWIND nodes(p) AS n RETURN n | WITH DISTINCT $-.n AS c RETURN c
(2)查询A,B,C的所有field
MATCH (c:class)-[:hasField]->(f:field) WHERE id(c) IN ["C", "B", "A"] RETURN f
我现在想把这两个查询整合到一起.
尝试1:
MATCH p=(v)-[:subclassOf*..10]->(s) WHERE id(v) == 'C' UNWIND nodes(p) AS n RETURN n | WITH DISTINCT $-.n AS c RETURN c | MATCH p=(c_)-[:hasField]->(f) WHERE id(c_) == id($-.c) RETURN f


这种ID匹配不行,那我在管道中传集合呢
尝试2:
MATCH p=(v)-[:subclassOf*..10]->(s) WHERE id(v) == 'C' UNWIND nodes(p) AS n RETURN n | WITH DISTINCT $-.n AS c RETURN c | WITH id($-.c) AS cid RETURN collect(cid) as cids | MATCH p=(c_)-[:hasField]->(f) WHERE id(c_) IN $-.cids RETURN f

一样的问题.那我用go,直接写上ID,不是在where里面写.
尝试3:
MATCH p=(v)-[:subclassOf*..10]->(s) WHERE id(v) == 'C' UNWIND nodes(p) AS n RETURN n | WITH DISTINCT $-.n AS c RETURN c | WITH id($-.c) AS cid RETURN cid | GO FROM $-.cid OVER hasField;

管道怎么没把值传过去.要不我通过接合的方式传过去试试.
尝试4:
MATCH p=(v)-[:subclassOf*..10]->(s) WHERE id(v) == 'C' UNWIND nodes(p) AS n RETURN n | WITH DISTINCT $-.n AS c RETURN c | WITH id($-.c) AS cid RETURN collect(cid) as cids | GO FROM $-.cids OVER hasField;

几经尝试.
正式向大佬们求助了.
用什么查询语句都可以.只要能写成一句.
当然,这里我用UNION可以这样查出来:
尝试5:
GO FROM "C" OVER hasField YIELD DISTINCT $$.field.name AS f UNION MATCH p=(v)-[:subclassOf*..10]->(s)-[:hasField]->(f) WHERE id(v) == 'C' RETURN f.name AS f;


这里返回的是节点的name字段.我想返回整个节点怎么处理.因为go的field里必须指定具体的属性.
GO FROM "C" OVER hasField YIELD DISTINCT $$.field AS f;

当然
尝试6:
GO FROM "C" OVER hasField YIELD hasField._dst AS fid | FETCH PROP ON field $-.fid UNION MATCH p=(v)-[:subclassOf*..10]->(s)-[:hasField]->(f) WHERE id(v) == 'C' RETURN f AS vertices_;

虽然出来了.这里面有两个瑕疵
(1)表头只能用vertices_
(2)从GO管道到FETCH.这里不知道是不是性能最佳的.

2 个赞

match是不支持输入的

就是说,不能在 ()-[]->() 模式里面填变量 ?

match语句都不支持

pipe基本没有额外的性能损失
go | fetch 和 match基本执行计划是差不多的,甚至因为match的优化还没做多少,性能会更好

尝试1,尝试2,尝试3,尝试4,可以帮我阶段一下为什么报错吗.我想细致的学习一下.知道为什么会这样报错.

根本原因都是不支持输入导致的

尝试1,尝试2 管道最后面的语句是match.但是尝试3,尝试4管道后面的语句是go.也不支持输入吗?

with也是match的一部分

MATCH p=(v)-[:subclassOf*…10]->(s) WHERE id(v) == ‘C’ UNWIND nodes(p) AS n RETURN n | WITH DISTINCT $-.n AS c RETURN c
这条里面有with.可以查询出来了.用到了管道传过来的变量 $-.n

这个目前是U.B.一样的东西,不要依赖它现在的行为

1 个赞

后续会让所有的语句增加输入和输出能力吗.我觉得这样管道的能力就更强大了.

match相关语句只支持输出,不支持输入;其他查询相关语句支持输入输出

match有计划支持输入么?这块其实很有用,好多场景都能用到

管道的功能是传递管道前变量并屏蔽管道前后子句之外的变量。管道其实是为早期 nGQL 语法设计的,更符合 go/lookup 等语法风格。

cypher 标准中没有管道的概念,子句及 pattern 之间的变量引用方式更自由,with 可以控制变量的可见域,是不需要管道的。我们目前不支持管道变量输入到 match 语句也是因为两者变量引用方式的差别,确实是 UB,反之(match 语句管道到 go/lookup 等) 是 nGQL 实现行为,可以保证正确。

你的需求可以通过 cypher 子句之间的组合来完成,这块目前还在开发,可以关注一下 nebula 后续的版本。

1 个赞

好的,谢谢老师这么详细的回复.
cypher中的一个特别逻辑是 match 可以和很多子句组合,比如return select insert,.这种组合,就像管道(效果上),match完了干嘛.而且match很强,有多patten.所有不需要管道那种多级的组合起来.

1 个赞

浙ICP备20010487号