概述
K邻模板子句khop().n()...n()
通过一个路径模板查询路径起点的K步邻居(简称K邻)。
根据设定的路径模板,K的值取决于两点间的最短距离,这符合K邻的定义。另外,返回的K邻需满足路径终点的过滤条件。
K邻 vs. K邻模板
K邻 |
K邻模板 |
|
---|---|---|
起点 | 单个 | 单个或多个 |
边的过滤条件 | 所有边一样 | 灵活 |
点的过滤条件(起点除外) | 所有点一样 | 灵活 |
路径模板 vs. K邻模板
K邻模板查询比实现同等效果的路径模板查询效率更高。
例如,以下两个嬴图GQL语句均返回指定用户点击的不同广告数量。需注意,路径模板返回的终点不会自动进行去重,而K邻模板的返回结果是去重的。
// 路径模板
n({_id == "u316591"}).e({@clicks}).n({@ad} as ads)
return count(DISTINCT ads)
// K邻模板
khop().n({_id == "u316591"}).e({@clicks}).n({@ad}) as ads
with count(ads)
语法
- 子句别名:NODE类型
- 关于路径模板:
- 第一个点模板
n()
的过滤条件不能为空,可指定多个点。 - 多边模板
e()[<steps>]
或e().nf()[<steps>]
不支持将[<steps>]
设置为[*:N]
格式,因为K邻查询原本就是根据最短路径进行遍历的。 - 不支持任何形式的步间过滤,无论是使用系统别名(
prev_n
、prev_e
)还是自定义别名。
- 第一个点模板
- 方法:
方法 |
参数类型 |
参数规范 |
必须 |
描述 | 别名 |
---|---|---|---|---|---|
limit() |
Integer | ≥-1 | 否 | 每个起点(注意不是每个子查询)返回的结果数,-1 表示返回所有 |
N/A |
示例
示例图集
![](https://img.ultipa.cn/draw/draw_29979ef7ec9e402498c5b69577e7e6a3.jpg?v='1713324743376')
在一个空图集中逐行运行以下语句创建示例图集:
create().node_schema("country").node_schema("movie").node_schema("director").node_schema("actor").edge_schema("filmedIn").edge_schema("direct").edge_schema("cast").edge_schema("bornIn")
create().node_property(@*, "name")
insert().into(@country).nodes([{_id:"C001", _uuid:1, name:"France"}, {_id:"C002", _uuid:2, name:"USA"}])
insert().into(@movie).nodes([{_id:"M001", _uuid:3, name:"Léon"}, {_id:"M002", _uuid:4, name:"The Terminator"}, {_id:"M003", _uuid:5, name:"Avatar"}])
insert().into(@director).nodes([{_id:"D001", _uuid:6, name:"Luc Besson"}, {_id:"D002", _uuid:7, name:"James Cameron"}])
insert().into(@actor).nodes({_id:"A001", _uuid:8, name:"Zoe Saldaña"})
insert().into(@filmedIn).edges([{_uuid:1, _from_uuid:3, _to_uuid:1}, {_uuid:2, _from_uuid:4, _to_uuid:1}, {_uuid:3, _from_uuid:4, _to_uuid:2}, {_uuid:4, _from_uuid:5, _to_uuid:2}])
insert().into(@direct).edges([{_uuid:5, _from_uuid:6, _to_uuid:3}, {_uuid:6, _from_uuid:7, _to_uuid:4}, {_uuid:7, _from_uuid:7, _to_uuid:5}])
insert().into(@cast).edges([{_uuid:8, _from_uuid:8, _to_uuid:5}])
insert().into(@bornIn).edges([{_uuid:9, _from_uuid:8, _to_uuid:2}])
设置固定长度路径
查找每个@country点经过特定路径可达的2步邻居。
khop().n({@country} as a).le({@filmedIn}).n({@movie}).le({@direct}).n({@director}) as b
return table(a.name, b.name)
结果:
a.name | b.name |
---|---|
USA | James Cameron |
France | James Cameron |
France | Luc Besson |
设置非固定长度路径
查找每个@country点经过特定路径可达的1~2步邻居。
khop().n({@country} as a).e({!@direct})[:2].n({!@country}) as b
return table(a.name, b.name)
结果:
a.name | b.name |
---|---|
USA | Zoe Saldaña |
USA | The Terminator |
USA | Avatar |
France | The Terminator |
France | Léon |
过滤终点
查找每个@country点的2步@director邻居。
khop().n({@country} as a).e()[2].n({@director}) as b
return table(a.name, b.name)
结果:
a.name | b.name |
---|---|
USA | James Cameron |
France | James Cameron |
France | Luc Besson |
经过最短路径
查找一个@actor点的2步@country邻居。
khop().n({@actor.name == "Zoe Saldaña"}).e()[2].n({@country}) as a return a
结果:无返回数据。
尽管该演员与一个国家间存在2步路径(Zoe Saldaña - [@cast] - Avatar - [filmedIn]- USA
),但那不是最短路径(Zoe Saldaña - [@bornIn] - USA
)。
使用limit()
通过特定路径,为每个@director点查找1个1步邻居。
khop().n({@director} as a).e({@direct}).n().limit(1) as b
return table(a.name, b.name)
结果:
a.name | b.name |
---|---|
James Cameron | The Terminator |
Luc Besson | Léon |
使用OPTIONAL
查找每个@actor点经过特定路径可达的2步邻居。无结果时返回null。
find().nodes({@country}) as cty
optional khop().n(cty).e({!@bornIn})[2].n({@actor}) as actor
return table(cty.name, actor.name)
结果:
cty._id | actor._id |
---|---|
France | null |
USA | Zoe Saldaña |