概述
使用语句khop().src().depth()
可以获取点的K步邻居信息。
一个点的K步邻居是距离该点最短距离为K的点,而最短距离就是最短路径中的边数。在图论中,一步指的是一个点经由一条边抵达另一个点的过程。
本图中,点A
的1步邻居为点{B, C, D}
,2步邻居为点{E, F, G}
,3步邻居为点{H}
。
K步邻居的主要特点如下:
K
仅由最短距离决定,且具有唯一性。例如,点A
和点C
之间有多条路径(如A-C
,A-D-C
,A-D-E-C
),而最短距离为1
。点C
只会作为点A
的1步邻居,不会出现在点A
的其他K邻查询结果中。- K邻查询结果已经去重。例如,点
A
和点E
间有两条最短路径(A-C-E
和A-D-E
),但在点A
的2步邻居查询结果中,点E
只会出现一次。
K邻查询采用了广度优先搜索(BFS)技术查找最短路径和K步邻居。嬴图已对K邻查询进行了优化,提高了查询效率。因此,在查询邻居节点时,建议使用K邻查询而非其他路径查询方法。
语法
khop().src(<filter?>).depth(<range>)
- 语句别名:类型为
NODE
- 方法:
方法 |
参数 |
描述 | 可选 |
别名类型 |
---|---|---|---|---|
src() |
<filter?> |
将过滤条件包裹在{} 中,或使用别名指定遍历的起点集。 留空时会作用在所有点上 |
否 | NODE |
depth() |
<range> |
K值(N≥0):
0 步路径时,返回遍历起点及其K步邻居 |
否 | N/A |
node_filter() |
<filter?> |
将针对邻居的过滤条件包裹在{} 中。留空则不应用任何过滤条件 |
是 | N/A |
edge_filter() |
<filter?> |
将针对最短路径中边的过滤条件包裹在{} 中。留空则不应用任何过滤条件 |
是 | N/A |
direction() |
<leftRight> |
指定路径中所有边的方向,可以为left 或right |
是 | N/A |
limit() |
<N> |
限制每个遍历起点返回的K邻数量(N ≥-1);-1 表示返回所有邻居 |
是 | N/A |
示例图集
在一个空图集中,逐行运行以下语句,创建示例图集:
create().edge_property(@default, "weight", int32)
insert().into(@default).nodes([{_id:"A"}, {_id:"B"}, {_id:"C"}, {_id:"D"}, {_id:"E"}, {_id:"F"}])
insert().into(@default).edges([{_from:"A", _to:"C", weight:1}, {_from:"E", _to:"B", weight:1}, {_from:"A", _to:"E", weight:4}, {_from:"D", _to:"C", weight:2}, {_from:"E", _to:"D", weight:3}, {_from:"B", _to:"A", weight:2}, {_from:"F", _to:"A", weight:4}])
查找K步邻居
N步内邻居
查找点D
的1到3步邻居:
khop().src({_id == "D"}).depth(1:3) as n
return collect(n._id)
结果:
collect(n._id) |
---|
["E","C","B","A","F"] |
N步邻居
查找点D
的3步邻居:
khop().src({_id == "D"}).depth(3) as n
return collect(n._id)
结果:
collect(n._id) |
---|
["F"] |
N到M步邻居
查找点D
的2到3步邻居:
khop().src({_id == "D"}).depth(2:3) as n
return collect(n._id)
结果:
collect(n._id) |
---|
["B","A","F"] |
过滤邻居
查找点D
的3步邻居,同时排除点E
:
khop().src({_id == "D"}).depth(3).node_filter({_id != "E"}) as n
return collect(n._id)
结果:
collect(n._id) |
---|
["F","B"] |
剔除点E
等同于将点E
和与其相连的边从图中移除。此时,图中最短路径结构有所变化,点B
因此成为点D
的3步邻居。
过滤边
分别查找点A
和点D
的1步邻居,同时剔除weight
属性大于3的边:
khop().src({_id in ["A", "D"]} as src).depth(1).edge_filter({weight <= 3}) as n
group by src
return src._id, count(n)
结果:
src._id | count(n) |
---|---|
D | 2 |
A | 2 |
剔除weight
属性大于3的边等同于将这些边从图中移除。图中最短路径结构因此改变。
设置边方向
查找点D
的1到2步邻居,并要求路径中的边方向为右:
khop().src({_id == "D"}).depth(:2).direction(right) as n
return collect(n._id)
结果:
collect(n._id) |
---|
["C"] |
返回起点
查找点D
的1步邻居,同时返回点D
:
khop().src({_id == "D"}).depth(0:1) as n
return collect(n._id)
结果:
collect(n._id) |
---|
["D","E","C"] |
限制查询数量
分别查询点A
和点D
的1到2步邻居,每个点只返回一个邻居:
khop().src({_id in ["D", "A"]}).depth(:2).limit(1) as n
return collect(n._id)
结果:
collect(n._id) |
---|
["E","F"] |
鉴于K邻查询的BFS本质,靠近起点的邻居(步数更少的点)会优先返回。
使用OPTIONAL
本条查询中,khop()
语句执行两次,每次使用start
中的一条记录。使用OPTIONAL
前缀后,如果没有查询到数据,则返回null
:
find().nodes({_id in ["A", "D"]}) as start
optional khop().src(start).depth(2).direction(right) as n
return table(start._id, n._id)
结果:
start._id | n._id |
---|---|
D | null |
A | D |
A | B |
若不使用OPTIONAL
前缀,则没有关于点D
的结果返回:
find().nodes({_id in ["A", "D"]}) as start
khop().src(start).depth(2).direction(right) as n
return table(start._id, n._id)
结果:
start._id | n._id |
---|---|
A | D |
A | B |