apoc.neighbors.byhop

Procedure APOC Core

apoc.neighbors.byhop(node, rel-direction-pattern, distance) - returns distinct nodes of the given relationships in the pattern at each distance, can use '>' or '<' for all outgoing or incoming relationships

Signature

apoc.neighbors.byhop(node :: NODE?, types =  :: STRING?, distance = 1 :: INTEGER?) :: (nodes :: LIST? OF NODE?)

Input parameters

Name Type Default

node

NODE?

null

types

STRING?

distance

INTEGER?

1

Output parameters

Name Type

nodes

LIST? OF NODE?

Usage Examples

The examples in this section are based on the following sample graph:

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)

The apoc.neighbors.byhop procedure compute a node’s neighborhood at multiple hop counts.

The following returns the people that Emil KNOWS up to 2 hops:

MATCH (p:Person {name: "Emil"})
CALL apoc.neighbors.byhop(p, "KNOWS", 2)
YIELD nodes
RETURN nodes
Table 1. Results
nodes

[(:Person {name: "Michael"})]

[(:Person {name: "Praveena"}), (:Person {name: "Lju"})]

From these results we can see that at level 1 Emil KNOWS Michael, and at level 2 Emil KNOWS Lju and Praveena. The following graph patterns describe how Emil knows the different people:

Level 1
  • (emil)-[:KNOWS]-(michael)

Level 2
  • (emil)-[:KNOWS]-(michael)-[:KNOWS]-(lju)

  • (emil)-[:KNOWS]-(michael)-[:KNOWS]-(praveena)

We can also use multiple relationship types when searching the neighborhood.

Let’s say that as well as finding the people that Emil knows, we also want to find the people that follow him. We can specify a direction to the relationship types, by using < to indicate an incoming relationship, or > to indicate an outgoing relationship. So to find people that follow Emil, we’d use <FOLLOWS.

The following returns the people that Emil KNOWS and those that have FOLLOWS relationships to him, at up to 3 hops:

MATCH (p:Person {name: "Emil"})
CALL apoc.neighbors.byhop(p, "KNOWS|<FOLLOWS", 3)
YIELD nodes
RETURN nodes
Table 2. Results
nodes

[(:Person {name: "Mark"}), (:Person {name: "Michael"})]

[(:Person {name: "Praveena"}), (:Person {name: "Joe"}), (:Person {name: "Lju"})]

[(:Person {name: "Ryan"})]

We’ve got some more results this time. Mark is in Emil’s level 1 neighborhood, Joe is in his level 2 neighborhood, and Ryan is in his level 3 neighborhood.

The following graph patterns describe how Emil knows the different people:

Level 1
  • (emil)-[:KNOWS]-(michael)

  • (mark)-[:FOLLOWS]→(emil)

Level 2
  • (emil)-[:KNOWS]-(michael)-[:KNOWS]-(lju)

  • (emil)-[:KNOWS]-(michael)-[:KNOWS]-(praveena)

  • (joe)-[:FOLLOWS]→(mark)-[:FOLLOWS]→(emil)

Level 3
  • (ryan)-[:FOLLOWS]→(joe)-[:FOLLOWS]→(mark)-[:FOLLOWS]→(emil)

And, as with the apoc.neighbors.athop procedure, we can also return just the neighborhood size at each hop.

The following returns the number of people that Emil KNOWS and the number that have FOLLOWS relationships to him, at up to 3 hops:

MATCH (p:Person {name: "Emil"})
CALL apoc.neighbors.byhop.count(p, "KNOWS|<FOLLOWS", 3)
YIELD value
RETURN value
Table 3. Results
value

[2, 3, 1]

And as expected we have a count of 2 at level 1, 3 at level 2, and 1 at level 3.

We could even turn that list of numbers into a map with the key being the number of hops and the value the neighborhood size. The following query shows how to do this using the apoc.map.fromLists function:

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
Table 4. Results
value

{1: 2, 2: 3, 3: 1}

If we aren’t interested in knowing which nodes are in our neighborhood, but just want a count of the number, we can do that as well. See apoc.neighbors.byhop.count.