概述
带量词路径模式定义变长路径,其中路径整体或部分重复指定次数。带量词路径模式将量词附加于边模式或带括号路径模式,形成带量词边或带量词路径。
<quantified path pattern> ::=
<quantified edges> | <quantified paths>
<quantified edges> ::=
<edge pattern> <quantifier>
<quantified paths> ::=
<parenthesized path pattern> <quantifier>
量词
量词以后缀形式出现在边模式或带括号路径模式之后。
量词 |
描述 |
---|---|
{m,n} |
重复m 到n 次 |
{m} |
重复m 次 |
{m,} |
重复至少m 次 |
{,n} |
重复0 到n 次 |
* |
重复至少0 次 |
+ |
重复至少1 次 |
当重复次数包括0
时,0条边的路径(或子路径),即只包含起始点的路径,将被纳入匹配结果中。
带量词边
通过在边模式后缀一个量词可构建带量词边,其中量词指定该边重复的次数。量词可应用于完整边模式和简写边模式。

此路径项等同于:

重复边隐式通过空点模式连接。
示例图

CREATE GRAPH myGraph {
NODE User ({name string}),
NODE Movie ({name string}),
EDGE Follows ()-[{}]->(),
EDGE Likes ()-[{}]->()
} PARTITION BY HASH(Crc32) SHARDS [1]
INSERT (purplechalk:User {_id: "U01", name: "purplechalk"}),
(mochaeach:User {_id: "U02", name: "mochaeach"}),
(rowlock:User {_id: "U03", name: "rowlock"}),
(quasar92:User {_id: "U04", name: "Quasar92"}),
(velvet:User {_id: "U05", name: "Velvet"}),
(brainy:User {_id: "U06", name: "Brainy"}),
(quickfox:User {_id: "U07", name: "Quickfox"}),
(inception:Movie {_id: "M01", name: "Inception"}),
(purplechalk)-[:Follows]->(mochaeach),
(mochaeach)-[:Follows]->(rowlock),
(rowlock)-[:Follows]->(quasar92),
(quasar92)-[:Follows]->(velvet),
(brainy)-[:Follows]->(mochaeach),
(mochaeach)-[:Likes]->(inception),
(quickfox)-[:Likes]->(inception)
固定下界和上界
获取Brainy
通过1~3条Follows
出边可到达的用户:
MATCH (:User {name: 'Brainy'})-[:Follows]->{1,3}(u:User)
RETURN COLLECT_LIST(u.name) AS names
结果:
names |
---|
["mochaeach", "rowlock", "Quasar92"] |
固定长度
获取Brainy
通过2条Follows
出边可到达的用户:
MATCH (:User {name: 'Brainy'})-[:Follows]->{2}(u:User)
RETURN COLLECT_LIST(u.name) AS names
结果:
names |
---|
["rowlock"] |
固定下界
获取Brainy
通过至少2条Follows
边可到达的用户:
MATCH (:User {name: 'Brainy'})-[:Follows]-{2,}(u:User)
RETURN COLLECT_LIST(u.name) AS names
结果:
names |
---|
["rowlock", "purplechalk", "Quasar92", "Velvet"] |
获取Brainy
通过至少0条Follows
出边可到达的用户:
MATCH (:User {name: 'Brainy'})-[:Follows]->*(u:User)
RETURN COLLECT_LIST(u.name) AS names
结果:
names |
---|
["Brainy", "mochaeach", "rowlock", "Quasar92", "Velvet"] |
获取Brainy
通过至少1条Follows
出边可到达的用户:
MATCH (:User {name: 'Brainy'})-[:Follows]->+(u:User)
RETURN COLLECT_LIST(u.name) AS names
结果:
names |
---|
["mochaeach", "rowlock", "Quasar92", "Velvet"] |
固定上界
获取Brainy
通过0~2条Follows
边可到达的用户:
MATCH (:User {name: 'Brainy'})-[:Follows]-{,2}(u:User)
RETURN COLLECT_LIST(u.name) AS names
结果:
names |
---|
["Brainy", "mochaeach", "rowlock", "purplechalk"] |
带量词简写边
简写边模式不对边标签或属性进行过滤。获取Brainy
通过1~2条边可到达的用户:
MATCH (:User {name: 'Brainy'})-{1,2}(u:User)
RETURN COLLECT_LIST(u.name) AS names
结果:
names |
---|
["mochaeach", "rowlock", "purplechalk", "QuickFox"] |
带量词路径
通过在带括号路径模式后缀一个量词可构建带量词路径,其中量词指定该路径重复的次数。

此路径项等同于:

相邻路径组由两个点模式连接。这些点模式会合并成单个点模式,同时合并过滤条件。在本例中,过滤条件只有User
标签:

合并后,简写为:

示例图

CREATE GRAPH myGraph {
NODE User ({name string}),
NODE Device (),
EDGE Owns ()-[{}]->(),
EDGE Flows ()-[{packets int32}]->()
} PARTITION BY HASH(Crc32) SHARDS [1]
INSERT (jack:User {_id: "U01", name: "Jack"}),
(mike:User {_id: "U02", name: "Mike"}),
(c1:Device {_id: "Comp1"}),
(c2:Device {_id: "Comp2"}),
(c3:Device {_id: "Comp3"}),
(c4:Device {_id: "Comp4"}),
(jack)-[:Owns]->(c1),
(mike)-[:Owns]->(c4),
(c1)-[:Flows {packets: 20}]->(c2),
(c1)-[:Flows {packets: 30}]->(c4),
(c2)-[:Flows {packets: 34}]->(c3),
(c2)-[:Flows {packets: 12}]->(c4),
(c3)-[:Flows {packets: 74}]->(c4)
固定下界和上界
获取从Jack
拥有的设备出发,通过1~3条出向数据流到达Mike
拥有的设备的路径,其中每条数据流包含超过15个数据包:
MATCH p = (:User {name: 'Jack'})-[:Owns]->
((:Device)-[f:Flows WHERE f.packets > 15]->(:Device)){1,3}
<-[:Owns]-(:User {name: 'Mike'})
RETURN p
结果:p

固定长度
获取从Jack
拥有的设备出发,通过3条出向数据流到达Mike
拥有的设备的路径,其中每条数据流包含超过15个数据包:
MATCH p = (:User {name: 'Jack'})-[:Owns]->
((:Device)-[f:Flows WHERE f.packets > 15]->(:Device)){3}
<-[:Owns]-(:User {name: 'Mike'})
RETURN p
结果:p

固定下界
获取从Jack
拥有的设备出发,通过至少2条出向数据流到达Mike
拥有的设备的路径,其中每条数据流包含超过15个数据包:
MATCH p = (:User {name: 'Jack'})-[:Owns]->
((:Device)-[f:Flows WHERE f.packets > 15]->(:Device)){2,}
<-[:Owns]-(:User {name: 'Mike'})
RETURN p
结果:p

获取从Jack
拥有的设备出发,通过至少0条出向数据流到达Mike
拥有的设备的路径,其中每条数据流包含超过15个数据包:
MATCH p = (:User {name: 'Jack'})-[:Owns]->
((:Device)-[f:Flows WHERE f.packets > 15]->(:Device))*
<-[:Owns]-(:User {name: 'Mike'})
RETURN p
结果:p

获取从Jack
拥有的设备出发,通过至少1条出向数据流到达Mike
拥有的设备的路径,其中每条数据流包含超过15个数据包:
MATCH p = (:User {name: 'Jack'})-[:Owns]->
((:Device)-[f:Flows WHERE f.packets > 15]->(:Device))+
<-[:Owns]-(:User {name: 'Mike'})
RETURN p
结果:p

固定上界
本例获取的路径从Jack
拥有的设备出发,通过0~2条出向数据流到达Mike
拥有的设备,其中每条数据流包含超过15个数据包:
MATCH p = (:User {name: 'Jack'})-[:Owns]->
((:Device)-[f:Flows WHERE f.packets > 15]->(:Device)){,2}
<-[:Owns]-(:User {name: 'Mike'})
RETURN p
结果:p

元素变量引用度
在带量词路径模式中声明的元素变量可能绑定到多个点或边。对这些变量的引用,其引用度会因引用位置的不同而变化。

单引用度
在带量词路径模式内部引用元素变量时,则该引用具有单引用度,即引用至多一个图元素。
MATCH p = ((a)-[]->(b) WHERE a.age < b.age){1,2}
RETURN p
结果:p

本查询中,a
和b
代表单个点。匹配路径时,条件a.age < b.age
用于评估每一对点a
和b
。
组引用度
如果引用出现在带量词路径模式外,则该引用具有组引用度,即引用完整的图元素列表。这种情况下,元素变量被视为组变量。
MATCH p = ((a)-[]->(b)){1,2}
RETURN p, a, b
结果:
p | a | b |
---|---|---|
![]() |
[{"id":"U02","uuid":"4179342653223075841","schema":"User","values":{"name":"Quasar92","age":29}}] | [{"id":"U03","uuid":"12393908373546860546","schema":"User","values":{"name":"claire","age":35}}] |
![]() |
[{"id":"U01","uuid":"9223374235878031361","schema":"User","values":{"name":"rowlock","age":24}}] | [{"id":"U02","uuid":"4179342653223075841","schema":"User","values":{"name":"Quasar92","age":29}}] |
![]() |
[{"id":"U01","uuid":"9223374235878031361","schema":"User","values":{"name":"rowlock","age":24}},{"id":"U02","uuid":"4179342653223075841","schema":"User","values":{"name":"Quasar92","age":29}}] | [{"id":"U02","uuid":"4179342653223075841","schema":"User","values":{"name":"Quasar92","age":29}},{"id":"U03","uuid":"12393908373546860546","schema":"User","values":{"name":"claire","age":35}}] |
RETURN
语句里的变量a
和b
都被视为组变量,分别代表匹配路径中的点列表,而非单个点。
以下查询有语法错误,因为它在带量词路径模式外将a
和b
视为单引用变量:
MATCH p = ((a)-[]->(b)){1,2}
WHERE a.age < b.age
RETURN p
暂不支持横向聚合功能。
组变量可用于聚合带量词边或带量词路径中的点或边数据,这称为横向聚合。
MATCH p = ()-[e]->{1,2}()
WHERE SUM(e.score) > 2
RETURN p, COLLECT_LIST(e.score) AS scores
结果:
p | scores |
---|---|
![]() |
[3] |
![]() |
[2,3] |