cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

Add a node label via CASE WHEN

I pick a node, lets say 'p4', then find all of its parents. I am interested in tagging all nodes that are connected to 'p4 with a label that represents how far they are from 'p4'. I came up with the code below.

MATCH upstream_path = (interesting_part:Part{PART_NAME:'p4'})-[:CHILD_OF*0..4]->(upstream_part:Part)
WHERE length(upstream_path) < 5 
WITH length(upstream_path) as level, nodes(upstream_path)[-1] as parents
CALL apoc.create.addLabels(parents, ['Level' + toString(level)]) YIELD node
RETURN count(parents) as count

However, i soon realized if there is a cycle in my graph, a node connecting to 'p4' can be assigned several new labels/levels/distances. For example, we can reach to a 'p4' neighboring node directly, or go through loop and reach it. In this case we will have 2 different distances assigned to that neighboring node. I would like to prevent this from happening. If i have already assigned a 'Level' Label to a node, i do not want to create another one.

I tried to use a CASE WHEN , but do not know how to call a cypher function inside it, and this fails.

MATCH upstream_path = (interesting_part:Part{PART_NAME:'p4'})-[:CHILD_OF*0..4]->(upstream_part:Part)
WHERE length(upstream_path) < 5 
WITH length(upstream_path) as level, nodes(upstream_path)[-1] as parents,  interesting_part
WITH length([x IN labels(parents) WHERE x STARTS WITH 'Level'])  AS result, parents
WITH CASE result WHEN 0 THEN  CALL apoc.create.addLabels( parents, ['Level' + toString(level)]) YIELD node ELSE 1 END AS output
RETURN output

Finally, i would really appreciate to know if there is a way for me to down-sample when showing the graph results. If i have thousands of nodes connected to 'p4', the graph can become really big to show. Is there a way to sample for example only 10 paths connecting to 'p4' rather than all paths connecting to 'p4' (e.g., can i put a limit statement in the middle of a cypher query?)

as a toy example you can try the following graph and notice 'p2' getting 2 labels.

CREATE (p1:Part{PART_NAME:'p1'})
CREATE (p2:Part{PART_NAME:'p2'})
CREATE (p3:Part{PART_NAME:'p3'})
CREATE (p4:Part{PART_NAME:'p4'})
CREATE (p5:Part{PART_NAME:'p5'})
CREATE (p6:Part{PART_NAME:'p6'})


CREATE (p2)-[:CHILD_OF]->(p1)
CREATE (p3)-[:CHILD_OF]->(p1)
CREATE (p4)-[:CHILD_OF]->(p2)
CREATE (p6)-[:CHILD_OF]->(p2)
CREATE (p2)-[:CHILD_OF]->(p5)
CREATE (p5)-[:CHILD_OF]->(p2)
2 REPLIES 2

CASE will only return a value.
Have a look at procedure apoc.do.case, that should let run a create query conditionally.
In pure cypher, the following "trick" would also work :
FOREACH (i IN CASE result WHEN 0 THEN [1] ELSE [] END | <do stuff here>)

You can use LIMIT after a WITH statement.

Please see our knowledge base article on conditional Cypher execution for an explanation and various solutions.