Reputation: 481
I have Neo4j community 3.5.5, where I built a graph data model with rail station and line sections between stations. Stations and line sections are nodes and connect is the relationship linking them.
I would like to name a starting station and an ending station and sum up length of all rail section in between. I tried the Cypher query below but Neo4j does not recognize line_section
as a node type.
match (n1:Station)-[:Connect]-(n2:Station)
where n1.Name='Station1' and n2.Name='Station3'
return sum(Line_Section.length)
I know it is possible to do the summing with Neo4j Traversal API. Is it possible to do this in Cypher?
Upvotes: 1
Views: 756
Reputation: 66947
Assuming the line section nodes have the label Line_Section
, you can use a variable-length relationship pattern to get the entire path, list comprehension to get a list of the line section nodes, UNWIND to get the individual nodes, and then use aggregation to SUM
all the line section lengths:
MATCH p = (n1:Station)-[:Connect*]-(n2:Station)
WHERE n1.Name='Station1' AND n2.Name='Station3'
UNWIND [n IN NODES(p) WHERE 'Line_Section' in LABELS(n)] AS ls
RETURN p, SUM(ls.length) AS distance
Or, you could use REDUCE
in place of UNWIND
and SUM
:
MATCH p = (n1:Station)-[:Connect*]-(n2:Station)
WHERE n1.Name='Station1' AND n2.Name='Station3'
RETURN p, REDUCE(s = 0, ls IN [n IN NODES(p) WHERE 'Line_Section' in LABELS(n)] |
s + ls.length) AS distance
[UPDATED]
Note: a variable-length relationship with an unbounded number of hops is expensive, and can take a long time or run out of memory.
If you only want the distance for the shortest path, then this should be faster:
MATCH
(n1:Station { name: 'Station1' }),
(n2:Station {name: 'Station3' }),
p = shortestPath((n1)-[*]-(n2))
WHERE ALL(r IN RELATIONSHIPS(p) WHERE TYPE(r) = 'Connect')
RETURN p, REDUCE(s = 0, ls IN [n IN NODES(p) WHERE 'Line_Section' in LABELS(n)] |
s + ls.length) AS distance
Upvotes: 1
Reputation: 5853
First capture
the path from a start node to the end node in a variable, then reduce
the length property over it.
MATCH path=(n1: Station { name: 'Station1' })-[:Connect]->(n2: Station { name: 'Station2' })
RETURN REDUCE (totalLength = 0, node in nodes(path) | totalLength + node.length) as totalDistance
Upvotes: 2