请问GET SUBGRAPH语句:是否支持对节点/边的类型 或 属性过过滤呢?

如题

看文档,支持的。(我用了最新发行版的文档

感谢,我看到最新文档说明,不支持schema函数吗?
如果要过滤目的点的类型是无法实现吗?

参考

get subgraph 2 steps
from "Tim Duncan" both serve
yield vertices as a 
| unwind $-.a as t 
| yield $-.t where "player" in tags($-.t)
2 个赞

谢谢,报语法错误,是哪里有问题吗,版本3.1.0

不要换行。

还是有错误呢

哪里语法错了,是不是用了中文符号还是什么原因,你调试一下语句看看吧。我上面发的示例是可以跑的。

你给的示例我也无法执行呢,对版本有要求吗,我使用的是3.1.0版本

另外我怎么调试ngql呢,调试源代码?

是的,你更新到3.4版本试试

是的,3.1.0 版本是不支持的,并不建议 unwind 和 get subgraph、go 这类原生 ngql 语句混用。
实际上你的需求并不需要用到 unwind,unwind 之后反而会丢失 get subgraph 返回结果的一部分语义,比如无法再区分子图层数。

3.3.0 版本 get subgraph 是支持属性过滤的,比如:

(root@nebula) [nba]> get subgraph with prop 1 steps from "Tim Duncan" both like,serve where $$.player.age>40 yield vertices as a 
+----------------------------------------------------------------------------------------------------------------------------+
| a                                                                                                                          |
+----------------------------------------------------------------------------------------------------------------------------+
| [("Tim Duncan" :player{age: 42, name: "Tim Duncan"} :bachelor{name: "Tim Duncan", speciality: "psychology"})]              |
| [("Manu Ginobili" :player{age: 41, name: "Manu Ginobili"}), ("Shaquile O'Neal" :player{age: 47, name: "Shaquile O'Neal"})] |
+----------------------------------------------------------------------------------------------------------------------------+
Got 2 rows (time spent 4907/5433 us)

(root@nebula) [nba]> get subgraph with prop 1 steps from "Tim Duncan" both like,serve where $$.player.age>43 yield vertices as a 
+---------------------------------------------------------------------------------------------------------------+
| a                                                                                                             |
+---------------------------------------------------------------------------------------------------------------+
| [("Tim Duncan" :player{age: 42, name: "Tim Duncan"} :bachelor{name: "Tim Duncan", speciality: "psychology"})] |
| [("Shaquile O'Neal" :player{age: 47, name: "Shaquile O'Neal"})]                                               |
+---------------------------------------------------------------------------------------------------------------+
Got 2 rows (time spent 4552/5007 us)

但是 subgraph 的属性过滤有很多限制,比如不支持 or 表达式,具体参考下文档: ngql subgraph

当然,你也可以不用 subgraph 的 where 来过滤结果集的属性(如果业务对性能不敏感的话),比如使用一些带谓词的表达式(比 subgraph where 支持更多的表达式类型):

(root@nebula) [nba]> get subgraph with prop 1 steps from "Tim Duncan" both like,serve yield vertices as a | yield [v in $-.a | v.player.age]
+----------------------------------------------------+
| [v IN $-.a | v.player.age]                         |
+----------------------------------------------------+
| [42]                                               |
| [32, 29, 36, 33, 34, 41, __NULL__, 31, 32, 47, 36] |
+----------------------------------------------------+
Got 2 rows (time spent 5968/6371 us)

(root@nebula) [nba]> get subgraph with prop 1 steps from "Tim Duncan" both like,serve yield vertices as a | yield [v in $-.a where v.player.age>40 or v.team.name>"A"| v] as a 
+------------------------------------------------------------------------------------------------------------------------------------------------------------+
| a                                                                                                                                                          |
+------------------------------------------------------------------------------------------------------------------------------------------------------------+
| [("Tim Duncan" :player{age: 42, name: "Tim Duncan"} :bachelor{name: "Tim Duncan", speciality: "psychology"})]                                              |
| [("Manu Ginobili" :player{age: 41, name: "Manu Ginobili"}), ("Spurs" :team{name: "Spurs"}), ("Shaquile O'Neal" :player{age: 47, name: "Shaquile O'Neal"})] |
+------------------------------------------------------------------------------------------------------------------------------------------------------------+
Got 2 rows (time spent 5968/6371 us)

(root@nebula) [nba]> """
                  -> get subgraph with prop 1 steps from "Tim Duncan" both like,serve yield vertices as a 
                  -> | yield [v in $-.a | 
                  ->     case when v.player.age is not null 
                  ->     then 
                  ->        (case when v.player.age>40 then [id(v),v.player.age] else null end)
                  ->     else 
                  ->        (case when v.team.name>"A" then [id(v), v.team.name] else null end)
                  -> end] as a 
                  -> """
+------------------------------------------------------------------------------------------------------------------------------------------------------+
| a                                                                                                                                                    |
+------------------------------------------------------------------------------------------------------------------------------------------------------+
| [["Tim Duncan", 42]]                                                                                                                                 |
| [__NULL__, __NULL__, __NULL__, __NULL__, __NULL__, ["Manu Ginobili", 41], ["Spurs", "Spurs"], __NULL__, __NULL__, ["Shaquile O'Neal", 47], __NULL__] |
+------------------------------------------------------------------------------------------------------------------------------------------------------+
Got 2 rows (time spent 6137/6577 us)
2 个赞

感谢感谢,既然您回复得这么详细,我就完整描述下我的需求背景:

我司目前使用3.1版本,通过get subgraph从指定的点出发查子图,此前发现不支持过滤条件,所以查出子图后在内存做二次过滤(包括节点tagName,边属性值过滤),再返回前端重新绘制子图。

但存在一个问题:原生语句查询出的子图是连通、完整的,做了二次过滤后部分点和边会被筛掉,子图常常会被拆分成多个小子图甚至孤立的点,不太满足业务上的需求

而我的要求是能支持类似这样的查询,伪代码:

get subgraph with prop 1 steps from “Tim Duncan” both serve
where tags(nodes) in [‘tag1’,‘tag2’] – 子图途经节点Tag过滤
and serve.time >= 20230101 and serve.time <= 20240101 – 子图途经边属性过滤
YIELD VERTICES AS nodes, EDGES AS relationships;

这样,如果查询的起点只有一个,最终返回的依然是一个联通的子图;

如果查询的起点是N个,最终返回的可能是<=N个联通的子图,因为可能多个子图之间是连通的,不被合并;

不知道版本3.3+,是否支持这样的查询呢

subgraph where 现在只支持 and 不支持 or,serve.time >= 20230101 and serve.time <= 20240101 这个是可以的,tags(nodes) in [‘tag1’,‘tag2’] 这个不行。确实 二次过滤会有这样的问题,目前并没有好的解决方案,一个比较 ugly 的做法是用单步 go 语句去实现类似子图的功能 :melting_face:,或者关注下之后的版本发布,可能会有 subgraph 相关的 enhancement。

就差tagName不支持吗?那真是太纠结了,几个问题:

1、那如果在点Tag上加属性,属性的值存储tagName,然后像边属性那样过滤,这样能变相实现吗?具体怎么写呢?类似这样吗?properties(nodes).column in [‘tag1’,‘tag2’]

2、go语句我尝试写了:
GO 1 TO 4 STEPS FROM “1872170” OVER edge_all BIDIRECT YIELD distinct src(edge) as src1,dst(edge) as dst1

但如何做到返回点和边,且附带相关属性呢:YIELD VERTICES AS nodes, EDGES AS relationships;

不是的。IN operator 隐含了逻辑或的语义,subgraph 语句目前还不支持逻辑或表达式。

go from "Tim Duncan" over like yield $^ as src,$$ as dst, edge as e;

也可以测一下 MATCH 语句,MATCH 在一定程度上兼容了 OpenCypher,语义表达更加灵活,但是性能不一定好。

好吧,既然subgraph无法支持,我只能尝试用go实现,下面是改写的例子:

GO 1 TO 2 STEPS FROM “1872170” OVER edge_all BIDIRECT
WHERE properties(edge).all_scene_earliest_time == 20211227000000
and (tags($$)[0] in [“finger_id”, “a”, “b”] OR tags($$)[0] in [“finger_id”, “a”, “b”])
YIELD $^ as src, $$ as dst, edge as e;

但tag过滤不知道怎么写,我希望起点或者终点的tag在指定的集合中,由于tags返回的是集合,一般来说集合元素是一个,但极端情况有个数不止一个的现象,所以我希望实现的是:
tags($$) 和 指定的集合 [“finger_id”, “a”, “b”] 之间有交集,请教该怎么写呢?

你是说一个点上有多个 tag,只要和指定的 tag 集合有交集就满足拓展条件哈?

对对,具体该怎么写呢,文档里和交集有关的关键字只有:INTERSECT 。