match与多Tag的兼容性

请教一下,在match语句里可以访问同一个vertex的不同tag的属性吗?我看文档里貌似是不可以的。

类似下面这样吗?

(root@nebula) [nba]> desc tag player
+--------+----------+-------+---------+
| Field  | Type     | Null  | Default |
+--------+----------+-------+---------+
| "name" | "string" | "YES" |         |
+--------+----------+-------+---------+
| "age"  | "int64"  | "YES" |         |
+--------+----------+-------+---------+
Got 2 rows (time spent 1317/1732 us)

Wed, 20 Jan 2021 17:01:18 CST

(root@nebula) [nba]> desc tag bachelor
+--------------+----------+-------+---------+
| Field        | Type     | Null  | Default |
+--------------+----------+-------+---------+
| "name"       | "string" | "YES" |         |
+--------------+----------+-------+---------+
| "speciality" | "string" | "YES" |         |
+--------------+----------+-------+---------+
Got 2 rows (time spent 1533/1984 us)

Wed, 20 Jan 2021 17:01:23 CST

(root@nebula) [nba]> match (v:player{name: "Tim Duncan"}) RETURN v.age, v.speciality, labels(v) as labels
+-------+--------------+------------------------+
| v.age | v.speciality | labels                 |
+-------+--------------+------------------------+
| 42    | "psychology" | ["bachelor", "player"] |
+-------+--------------+------------------------+
Got 1 rows (time spent 6767/7186 us)

Wed, 20 Jan 2021 17:01:26 CST

player和bachelor两个tag都有name属性,return v.name的时候我试了好像只会返回其中一个tag的name属性,而通过GO语句是可以指定哪个tag的name属性的

这里是为了跟 openCyher 保持兼容,才做成这样的。其实客户端是把所有的 tag 的属性都返回了,如果你要在客户端使用,可以直接拿点,然后自己去拿哪个 tag 的哪个属性都是可以的:

(root@nebula) [nba]> match (v:player{name: "Tim Duncan"}) RETURN v
+-------------------------------------------------------------------------------------------------------------+
| v                                                                                                           |
+-------------------------------------------------------------------------------------------------------------+
| ("Tim Duncan" :bachelor{name: "Tim Duncan", speciality: "psychology"} :player{age: 42, name: "Tim Duncan"}) |
+-------------------------------------------------------------------------------------------------------------+
Got 1 rows (time spent 7388/7821 us)

Wed, 20 Jan 2021 17:15:05 CST
1 个赞

在where条件里有办法基于player的name进行过滤吗?

就这个 case 而言,已经使用了 player.name 进行的过滤,为什么还要在 WHERE 中再加过滤呢?能否写一下你的使用用例?

是这样,我是希望通过vid的方式选定起始点,假设通过follow关系跳转到v2,v2也是具有player和bachelor两个tag,这时我想通过player的name属性对v2进行过滤,这个有办法实现吗?

如果像示例中的 player 和 bachelor 一样,有相同的 tag 属性,match 中是不好区分哪个 tag 的。这个如果又是必须的话,可以使用 GO 来实现。

预格式化文本将缩进 4 格
match (v)-[:follow]->(v2) where id(v) == 'player102' and v2.name== 'Tony Parker' return v2;
[ERROR (-8)]: Can't solve the start vids from the sentence: MATCH (v)-[:follow]->(v2) WHERE ((id(v)==player102) AND (v2.name==Tony Parker)) RETURN v2

还有个问题麻烦也看下,按照我刚才说的case,报这个错,但是我对v2的条件应该跟起始vid无关吧?

你好,这里是 MATCH 的实现的问题,现在索引提取还有一些工作正在做,目前的 case 可以通过如下的方式来规避一下:

(root@nebula) [nba]> match p=(v)-[:like]-(v2 {name: "Tony Parker"}) where id(v) == "Tim Duncan" return v2, p
+-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| v2                                                    | p                                                                                                                                                                                             |
+-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ("Tony Parker" :player{age: 36, name: "Tony Parker"}) | <("Tim Duncan" :bachelor{name: "Tim Duncan", speciality: "psychology"} :player{age: 42, name: "Tim Duncan"})<-[:like@0 {likeness: 95}]-("Tony Parker" :player{age: 36, name: "Tony Parker"})> |
+-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ("Tony Parker" :player{age: 36, name: "Tony Parker"}) | <("Tim Duncan" :bachelor{name: "Tim Duncan", speciality: "psychology"} :player{age: 42, name: "Tim Duncan"})-[:like@0 {likeness: 95}]->("Tony Parker" :player{age: 36, name: "Tony Parker"})> |
+-------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
Got 2 rows (time spent 8845/9414 us)

Thu, 21 Jan 2021 10:01:20 CST
2 个赞

版本:Nebula Graph 2.0.0-rc1

使用 match ,利用 where 对 vertex and edge 做条件过滤时,遇到类似的问题

对 source vertex 的 id 和 edge 的一个 timestamp 属性 exec_time 做过滤,报错 Can't solve the start vids from the sentence

如果去掉 edge exec_time 的过滤条件,可以正常查询。


请问如何利用 where 进行查询?或者按照 @yee 大佬给出的方式,在 edge 的属性中过滤,{} 里如何写 “大于等于某个数值” 的条件?

Fixed in PR https://github.com/vesoft-inc/nebula-graph/pull/500

问一下,match这块后续有考虑兼容多Tag的情况吗?譬如通过函数扩展一下。

以之前的player和bachelor两个tag都有name属性为例,在过滤时可以通过类似:getProperty(v2, bachelor, name) == ‘Tim Duncan’,第二个参数指定了Tag

Good point!

nebula 的目标是最大可能的兼容 openCypher 中的 MATCH 功能,像你说的多 TAG 的情况,如果 openCypher 中可以,nebula 将来也会努力去支持,目前的 MATCH 的功能还只是一小步,其中的功能点有很多,需要一定的时间来完善,但是从实现的角度来讲是没有问题。

我从 openCypher 的文档中没有看到 getProperty 的函数,上面的表达式或许可以通过类似的方式来表达:

MATCH (v2:bachelor{name: "Tim Duncan"}:player)

不过这种是表达 equal 的形式,如果是不等可能需要考虑你的建议方式。 @steam 这个问题可以记录一下,看看是否有好的方式或者变为需求。

3 个赞

版本:Nebula Graph 2.0.0-GA
尝试用 GA 版本去做上述多属性的查询,比如:

match (src) -[e:data_flow]- (dst) where id(src)=="src_vertex_id" and e.exec_time>=1616601600 return src, e, dst

可以查询成功,GREAT !

但如果是查询多跳,如下则无返回(连上述第一跳的结果都没有了):

match (src) -[e:data_flow*1..2]- (dst) where id(src)=="src_vertex_id" and e.exec_time>=1616601600 return src, e, dst

用 GO 语句是能够查询到相应的上下游多跳。

@yee

1 个赞

先说下我本地验证的结论:

(user@nebula) [nba]> match (v)-[e:like]-(v2) where id(v)=="Tim Duncan" and e.likeness>90 return v2
[ERROR (-8)]: Can't solve the start vids from the sentence: MATCH (v)-[e:like]-(v2) WHERE ((id(v)=="Tim Duncan") AND (e.likeness>90)) RETURN v2

Sun, 28 Mar 2021 23:51:30 CST

(user@nebula) [nba]> match (v)-[e:like*1..2]-(v2) where id(v)=="Tim Duncan" and e.likeness>90 return v2
[ERROR (-8)]: Can't solve the start vids from the sentence: MATCH (v)-[e:like*..2]-(v2) WHERE ((id(v)=="Tim Duncan") AND (e.likeness>90)) RETURN v2

Sun, 28 Mar 2021 23:51:40 CST

(user@nebula) [nba]> match (v:player)-[e:like]-(v2) where id(v)=="Tim Duncan" and e.likeness>90 return v2
+---------------------------------------------------------------+
| v2                                                            |
+---------------------------------------------------------------+
| ("Dejounte Murray" :player{age: 29, name: "Dejounte Murray"}) |
+---------------------------------------------------------------+
| ("Tony Parker" :player{age: 36, name: "Tony Parker"})         |
+---------------------------------------------------------------+
| ("Manu Ginobili" :player{age: 41, name: "Manu Ginobili"})     |
+---------------------------------------------------------------+
| ("Tony Parker" :player{age: 36, name: "Tony Parker"})         |
+---------------------------------------------------------------+
Got 4 rows (time spent 68064/68469 us)

Sun, 28 Mar 2021 23:51:52 CST

(user@nebula) [nba]> match (v:player)-[e:like*1..2]-(v2) where id(v)=="Tim Duncan" and e.likeness>90 return v2
Empty set (time spent 476908/477156 us)

Sun, 28 Mar 2021 23:52:02 CST

明天我到公司看下这里的实现问题,有结论了再回复你。

1 个赞

抱歉,今天才有时间帮你看这个问题,针对变长的 MATCH 第二种写法是有问题的,因为是变长这时的 e 表示的其实是个边的 list,所以这里变长的正确写法应该是:

match (src) -[e:data_flow*1..2]- (dst) 
where id(src)=="src_vertex_id" and e[0].exec_time>=1616601600
return src, e, dst

表示的是对第一度的边过滤

1 个赞

如何对所有的 e 进行过滤呢?

可以试试 all 函数:

match (src) -[e:data_flow*1..2]- (dst) 
where id(src)=="src_vertex_id" and all(t IN e WHERE t.exec_time>=1616601600)
return src, e, dst
6 个赞