邻居函数
邻居搜索过程能够快速发现基于特定关系类型和跳数的周围节点。
可用过程
下表描述了可用过程
限定名 | 类型 |
---|---|
apoc.neighbors.athop |
|
apoc.neighbors.byhop |
|
apoc.neighbors.tohop |
|
关系过滤器
邻居搜索过程中,每个过程的第二个参数都是关系过滤器。关系过滤器是一个由 |
分隔的关系类型列表,使用以下语法:
Syntax: [<]RELATIONSHIP_TYPE1[>]|[<]RELATIONSHIP_TYPE2[>]|…
输入 | 类型 | 方向 |
---|---|---|
|
|
出站 |
|
|
入站 |
|
|
双向 |
|
|
出站 |
|
|
入站 |
关系过滤器对空格敏感,因此,如果您没有看到预期结果,请检查(并删除!)末尾的空格。 |
示例
本节中的示例基于以下示例图
MERGE (mark:Person {name: "Mark"})
MERGE (praveena:Person {name: "Praveena"})
MERGE (joe:Person {name: "Joe"})
MERGE (lju:Person {name: "Lju"})
MERGE (michael:Person {name: "Michael"})
MERGE (emil:Person {name: "Emil"})
MERGE (ryan:Person {name: "Ryan"})
MERGE (ryan)-[:FOLLOWS]->(joe)
MERGE (joe)-[:FOLLOWS]->(mark)
MERGE (mark)-[:FOLLOWS]->(emil)
MERGE (michael)-[:KNOWS]-(emil)
MERGE (michael)-[:KNOWS]-(lju)
MERGE (michael)-[:KNOWS]-(praveena)
MERGE (emil)-[:FOLLOWS]->(joe)
MERGE (praveena)-[:FOLLOWS]->(joe)
KNOWS
关系类型被认为是双向的,如果 Michael 认识 Emil,我们就可以推断 Emil 也认识 Michael。使用 KNOWS
关系时,我们将忽略方向。
FOLLOWS
关系具有方向,因此,在使用它时我们将指定方向。
查找指定跳数的邻居
apoc.neighbors.athop
过程计算节点在特定跳数上的邻居。
KNOWS
的人物MATCH (p:Person {name: "Emil"})
CALL apoc.neighbors.athop(p, "KNOWS", 1)
YIELD node
RETURN node
节点 |
---|
(:Person {name: "Michael"}) |
Emil 只与 Michael 有直接的 KNOWS
关系,因此 Michael 是此查询返回的唯一节点。
KNOWS
的人物MATCH (p:Person {name: "Emil"})
CALL apoc.neighbors.athop(p, "KNOWS", 2)
YIELD node
RETURN node
节点 |
---|
(:Person {name: "Praveena"}) |
(:Person {name: "Lju"}) |
Michael 也 KNOWS
Praveena 和 Lju,由于 Emil 不直接 KNOWS
他们,所以他只在跳数为 2 的距离上 KNOWS
他们。如果我们不关心邻居中有哪些节点,而只是想知道数量,我们也可以这样做。
KNOWS
的人数MATCH (p:Person {name: "Emil"})
CALL apoc.neighbors.athop.count(p, "KNOWS", 2)
YIELD value
RETURN value
值 |
---|
2 |
正如所料,我们得到了 2 的计数,他们就是 Praveena 和 Lju!
查找指定跳数范围内的邻居
apoc.neighbors.byhop
过程计算节点在多个跳数上的邻居。
KNOWS
的人物MATCH (p:Person {name: "Emil"})
CALL apoc.neighbors.byhop(p, "KNOWS", 2)
YIELD nodes
RETURN nodes
节点 |
---|
[(:Person {name: "Michael"})] |
[(:Person {name: "Praveena"}), (:Person {name: "Lju"})] |
从这些结果中我们可以看到,在第 1 层,Emil KNOWS
Michael;在第 2 层,Emil KNOWS
Lju 和 Praveena。以下图模式描述了 Emil 如何认识不同的人:
-
(emil)-[:KNOWS]-(michael)
-
(emil)-[:KNOWS]-(michael)-[:KNOWS]-(lju)
-
(emil)-[:KNOWS]-(michael)-[:KNOWS]-(praveena)
在搜索邻居时,我们还可以使用多种关系类型。
假设除了找到 Emil 认识的人之外,我们还想找到关注他的人。我们可以为关系类型指定方向,使用 <
表示入站关系,或使用 >
表示出站关系。因此,要找到关注 Emil 的人,我们将使用 <FOLLOWS
。
KNOWS
的人和与他有 FOLLOWS
关系的人MATCH (p:Person {name: "Emil"})
CALL apoc.neighbors.byhop(p, "KNOWS|<FOLLOWS", 3)
YIELD nodes
RETURN nodes
节点 |
---|
[(:Person {name: "Mark"}), (:Person {name: "Michael"})] |
[(:Person {name: "Praveena"}), (:Person {name: "Joe"}), (:Person {name: "Lju"})] |
[(:Person {name: "Ryan"})] |
这次我们得到了更多结果。Mark 在 Emil 的第 1 层邻居中,Joe 在他的第 2 层邻居中,Ryan 在他的第 3 层邻居中。
以下图模式描述了 Emil 如何认识不同的人:
-
(emil)-[:KNOWS]-(michael)
-
(mark)-[:FOLLOWS]→(emil)
-
(emil)-[:KNOWS]-(michael)-[:KNOWS]-(lju)
-
(emil)-[:KNOWS]-(michael)-[:KNOWS]-(praveena)
-
(joe)-[:FOLLOWS]→(mark)-[:FOLLOWS]→(emil)
-
(ryan)-[:FOLLOWS]→(joe)-[:FOLLOWS]→(mark)-[:FOLLOWS]→(emil)
与 apoc.neighbors.athop
过程一样,我们也可以只返回每个跳数的邻居大小。
KNOWS
的人数和与他有 FOLLOWS
关系的人数MATCH (p:Person {name: "Emil"})
CALL apoc.neighbors.byhop.count(p, "KNOWS|<FOLLOWS", 3)
YIELD value
RETURN value
值 |
---|
[2, 3, 1] |
正如所料,我们在第 1 层有 2 个计数,第 2 层有 3 个,第 3 层有 1 个。
我们甚至可以将该数字列表转换为映射,其中键是跳数,值是邻居大小。以下查询展示了如何使用 apoc.map.fromLists
函数实现此操作
MATCH (p:Person {name: "Emil"})
CALL apoc.neighbors.byhop.count(p, "KNOWS|<FOLLOWS", 3)
YIELD value
RETURN apoc.map.fromLists(
[value in range(1, size(value)) | toString(value)],
value) AS value
值 |
---|
{ |
查找指定跳数以内的邻居
apoc.neighbors.tohop
过程计算节点在指定跳数以内的邻居。
FOLLOWS
的人物MATCH (p:Person {name: "Praveena"})
CALL apoc.neighbors.tohop(p, "FOLLOWS>", 1)
YIELD node
RETURN node
节点 |
---|
(:Person {name: "Joe"}) |
Praveena 唯一关注的人是 Joe,所以这是返回的唯一节点。如果我们包含 2 跳距离以内的人呢?
FOLLOWS
的人物MATCH (p:Person {name: "Praveena"})
CALL apoc.neighbors.tohop(p, "FOLLOWS>", 2)
YIELD node
RETURN node
节点 |
---|
(:Person {name: "Mark"}) |
(:Person {name: "Joe"}) |
现在 Mark 也被返回了。以下图模式描述了 Emil 如何认识不同的人:
-
(praveena)-[:FOLLOWS]-(joe)
-
(praveena)-[:FOLLOWS]-(joe)-[:FOLLOWS]→(mark)
如果我们只想知道人数,可以使用计数变体。
FOLLOWS
的人数MATCH (p:Person {name: "Praveena"})
CALL apoc.neighbors.tohop.count(p, "FOLLOWS>", 2)
YIELD value
RETURN value
值 |
---|
2 |