Search code examples
node.jsgraphneo4jgraph-traversalneo4j-driver

how to match right and left nodes with cypher and neo4j


I try to use a Neo4J graph database in my project, and I'll try to explain you my problem.

I would like to have the longest path, within the limit of 8 nodes, on right and left of each result. But I don't know the last node of each end of my graph

The following diagram is a basic example. My graph is built like a chain, like this :

My DB - Neo4j diagram

My problem is to find the left and right nodes. With this dummy query, I have duplicate results

MATCH p=((nl)<-[:PREV*0..8]-(i)-[:NEXT*0..8]->(nr)) RETURN nodes(p);

This returns too much duplicate results. Here some samples of results :

i
h | i
g | h | i
...
i | j
i | j | k
...
h | i | j
h | i | j | k
...
a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q

The last result is the only one that interests me.

It seems that Neo4j returns all possible combinations of nodes to the left and to the right within the limit of 8.

Additional information:

  • There can be several "middle nodes" ('i' in the example)
  • I want 8 nodes to the left, 8 to the right or less, but always the max number of nodes on both sides

Is it possible to perform this with Cypher?


Solution

  • If you only need one, then order by the length of the path and limit to a single result:

    MATCH p=((nl)<-[:PREV*0..8]-(i)-[:NEXT*0..8]->(nr)) 
    WITH p
    ORDER BY length(p) DESC
    LIMIT 1
    RETURN nodes(p);
    

    Alternately you can match and gather on each side:

    MATCH p=(nl)<-[:PREV*0..8]-(i)
    WITH i, nl
    ORDER BY length(p) DESC
    WITH i, collect(nl) as nodes
    MATCH p = (i)-[:NEXT*1..8]->(nr)
    WITH nodes, i, nr
    ORDER BY length(p) ASC
    WITH i, nodes + collect(nr) as nodes
    RETURN nodes;