In my project, Neo4J stores staff nodes and relationships between staff.

People who have been to the same place within A period of time will have A relationship. For example, A and B have arrived at the same scene within A day, and A and B will have an association relationship.

I need to focus on any one person and find all the people within three degrees of path depth. My search statement is as follows:

MATCH p = (x:user)-[r:REL*1..3]->(y:user)

where x.user_id = '20121'

UNWIND NODES(p) AS n

WITH p,

SIZE(COLLECT(DISTINCT n)) AS testLength

WHERE testLength = LENGTH(p) + 1

RETURN p

When the site is small, there is no problem in searching in this way, and the path is obtained:

[p1->p2]、[p1->p3]、[p1->p4]

[p1->p2->p5]、[p1->p3->p6]、[p1->p4->p7]

[p1->p2->p5->p8]、[p1->p3->p6->p9]、[p1->p4->p7->p10]

When there are more people in the place, the number of paths will change a lot. For example, when 10 people arrive at a place, the number of paths will be

`10*9*8`

:

When 10,000 people arrive at a site, the number of paths is

`1000*999*988`

, which is a disaster

[p1->p2]...[p1->p10]

[p1->p2->p3]...[p1->p2->p10]

[p1->p3->p2]...[p1->p3->p10]

....

[p1->p2->p3->p4]....[p1->p2->p3->p10]....

[p1->p10->p9->p8]....[p1->p10->p9->p1]....

....

I do not know how to deal with this situation, hope to get help

This is my data script

export-1.txt (3.8 KB)

export-2.txt (16.7 KB)

@mengyunlong

I don't know if it's what you need,

but If you can use APOC procedures maybe you could write your query like this:

```
MATCH p = (x:user)-[r:REL*1..3]->(y:user)
where x.user_id = '20121'
with collect(NODES(p)) as nodes, collect(relationships(p)) as rels
return apoc.coll.toSet(apoc.coll.flatten(nodes)) as nodes, apoc.coll.toSet(apoc.coll.flatten(rels)) as rels
```

or with a map return:

```
return {nodes: apoc.coll.toSet(apoc.coll.flatten(nodes)), rels: apoc.coll.toSet(apoc.coll.flatten(rels))}
```

If your use case is to find distinct people within 3 degrees (and you don't actually care about distinct paths the way Cypher does) then you can use `apoc.path.subgraphNodes()`

, a path expander procedure in APOC Procedures that is optimized for finding distinct nodes (and pruning any path found to a previously-encountered node).

```
MATCH (x:user)
WHERE x.user_id = '20121'
CALL apoc.path.subgraphNodes(x, {maxLevel:3, relationshipFilter:'REL>', labelFilter:'>user'}) YIELD node as y
RETURN y
```

This will only give distinct nodes back, it won't give back paths. If you want paths, then use `apoc.path.spanningTree()`

instead, but be aware that it will only give back a single path per reached nodes, not multiple paths.

Thank you for your help. Maybe I didn't express it clearly in my question. Is there any way to query only the shortest path, for example, query only [P1 ->p2], [P1 ->p3]... [p1 - > p10] such a shortest path, exclude [p1 - > p3 - > p2], [p1 - > p4 - > p3 - > p2] such a path

Thanks for your help I need to find not only nodes, but also the shortest path between nodes. This is what I want: Nodes :[P2, P3, P4, P5, P6, P7, P8, P9, P10], rel: [p1 - > p2], [p1 - > p3], [p1 - > p4], [p1 - > p5], [p1 - > p6], [p1 - > p7], [p1 - > p8], [p1 - > p9], [p1 - > p10]

I do not know how to write such a statement, looking forward to your help

In this case you'll need to use `apoc.path.spanningTree()`

, which does `YIELD path`

instead of node.

The paths will automatically be shortest paths, since the procedure uses breadth-first expansion, and will only use the first path found to a node and no other.

1 Like

thanks a lot! The apoc.path.spanningTree() function solved my problem. thanks again!