2

I'm new to neo4j and cypher, with about a week's experience... I'm working on a small project to manipulate with a graph of the 10s of thousands of TWS batch jobs running on the mainframe of my company. A key mission is to found out what we called key-path of the batch jobs of the last batch in the midnight, which is actually the weighted shortestPath in neo4j. I have already achieved that goal using a cypher like below.

MATCH (a:Job {Jobname:...}),(b:Job {Jobname:...}) 
call apoc.algo.dijkstra(a,b,'runafter>','Duration') YIELD path, weight
RETURN path,weight`

I created a python with neo4j driver and it runs every day automatically, to extract the batch jobs data from rbdms and created a new graph every day in neo4j and run the cyphers and format the result key-path to fit my MySQL so that I can compare the key-path of every different day

But a new idea came to my mind, what if I can enhance this cypher so that the nodes along the returned path will be set a label/or a property? so that I can later easily refer to the key-path again without calling the Dijkstra every time. I know I can use my python program to do that, just after the key-path is back and generate a series of cypher to do that job, but I think there should be a solution with cypher alone. Thanks a lot in advance!

stdob--
  • 28,222
  • 5
  • 58
  • 73
AlexDxl
  • 23
  • 5

1 Answers1

2
  1. Compute the path identifier value
  2. You need to take the array of nodes along the path - NODES
  3. Go through each node - UNWIND or FOREACH
  4. Set or label or property - now you can not use the value of a variable as a label, it means writing to the property - SET

MATCH (a:Job {Jobname:...}),(b:Job {Jobname:...}) WITH a, b,
     a.Jobname + '-' + b.Jobname AS pathID
CALL apoc.algo.dijkstra(a,b,'runafter>','Duration') YIELD path, weight
FOREACH (n IN NODES(path)|
  SET n.pathID = pathID,
      n.pathWeight = weight
)
RETURN path,weight

Since you use apoc, you can set labels:

MATCH (a:Job {Jobname:...}),(b:Job {Jobname:...}) WITH a, b,
     'inCalculatedPath' + '-' + a.Jobname + '-' + b.Jobname AS pathID
CALL apoc.algo.dijkstra(a,b,'runafter>','Duration') YIELD path, weight
CALL apoc.create.addLabels( NODES(path), ['inCalculatedPath', pathID])
RETURN path,weight

An additional way is to add the something like Calculated path node:

MATCH (a:Job {Jobname:...}),(b:Job {Jobname:...}) WITH a, b
CALL apoc.algo.dijkstra(a,b,'runafter>','Duration') YIELD path, weight
CREATE (P:CalculatedPath) 
  SET P.weight = weight,
      P.start = ID(a),
      P.end = ID(b),
      P.pathNodes = REDUCE(ids=[], n IN NODES(path)| ids + ID(n)),
      P.pathRels  = REDUCE(ids=[], r IN RELS(path) | ids + ID(r))
FOREACH (n IN NODES(path)|
  MERGE (n)-[:inPath]->(P)
)
RETURN path, weight

And get paths back:

MATCH (a:Job {Jobname:...}),(b:Job {Jobname:...}) WITH a, b
MATCH (path:CalculatedPath {start: ID(A), end: ID(b)})
RETURN path, path.weight AS weight
stdob--
  • 28,222
  • 5
  • 58
  • 73
  • Thank you so much! I tried all the cyphers and they just work like charm!! Those great example really helped me to better understand the power of cypher and neo4j... Thanks again! – AlexDxl Mar 09 '17 at 13:46