Neo4j - Paths having all nodes with specific label (Operations on labels) - neo4j

I want to retrieve paths between nodes with constraint on node label. All nodes in the path should hold a specific label. "amps" is my label and
My query:
MATCH p=(a:amps{word:"review"})-->()-->()-->(b:amps{word:"nothing"})
RETURN p
In the above query, I have two intermediate nodes. Now, I want these two nodes should also hold the label "amps".
How to make comparisons on labels?

If ALL the nodes in the path should have the amps label and with you current query you can do this in two ways :
1) Specify the labels in the () :
MATCH p=(a:amps{word:"review"})-->(:amps)-->(:amps)-->(b:amps{word:"nothing"})
RETURN p
2) Specify it with the ALL predicate :
MATCH p=(a:amps{word:"review"})-->()-->()-->(b:amps{word:"nothing"})
WHERE ALL ( n IN nodes(p) WHERE "amps" IN labels(n) )
RETURN p

Related

Need to Add new property to all the labels expect the label name not starts like 'IA_' in neo4j cypher

I want to add new property for all lables except the lable name starts with 'x'
I have tried the below cyper query but it's failing.
MATCH (n)
WITH DISTINCT labels(n) AS label
UNWIND label AS names
WITH names AS candidate
WHERE candidate =~ '^(.?$|[^I].+|I[^A].*)*'
CALL apoc.create.setProperty(labels(candidate),'link','')
YIELD node
return node
You cannot add properties to labels. You can only add properties to nodes that have certain labels.
MATCH (n)
WHERE NONE( label IN labels(n) WHERE label STARTS WITH ‘IA_’ )
SET n.myProperty = myValue
adds a property to nodes not having a label starting with IA_

How to find the count of distinct nodes between a single node of particular label to all other nodes in a different label in neo4j?

I have 4 different types of labels and multiple nodes in each. Let's say Node A of label P is connected to multiple nodes of label Q and those nodes are connected to multiple nodes of label R. Now I'm trying to figure out the count of distinct nodes in label R that is connected to Node A either directly or through label Q.
This should work:
MATCH path = (a:P)-[*1..2]->(r:R)
WHERE a.id = 'A' AND (LENGTH(path) = 1 OR 'Q' IN LABELS(NODES(path)[1]))
RETURN DISTINCT r
This simple example assumes a consistent "forward" relationship directionality for both relationships.
[ADDENDUM]
This should be a better query than that one asked about in the comments:
MATCH path = allShortestPaths((a:P)-[*1..2]->(r:R))
WHERE a.id = $resource_key AND (LENGTH(path) = 1 OR 'Q' IN LABELS(NODES(path)[1]))
RETURN COUNT(DISTINCT r)

How to find all labels that contain string in neo4j

Trying to get all nodes of a certain label type. I have roots of multiple graphs that all have the same suffix in their labels. For example, i have 3 nodes that all have treeroot at the end of their label. So I might have companytreeroot, buildingtreeroot, nd employeetreeroot as 3 valid labels for 3 distinct nodes. How would I get all nodes whose label has that pattern?
I tried:
match (n) where '.*treeroot' in labels(n) return n
and
match (n) where 'treeroot' in labels(n) return n
but both return empty sets...
stdob--'s answer works, but it must inspect all labels of all nodes in your graph, so this becomes more and more expensive as your graph grows.
A faster approach involves first finding the labels that match quickly by using the db.labels() procedure, then (because Cypher does not natively support dynamic label queries) use APOC Procedures' cypher.run() procedure to use String concatenation to assemble a query that finds all nodes in all the labels that met your match.
Here's an example that should be quite fast, even on large graphs:
CALL db.labels() YIELD label
WITH label
WHERE label ENDS WITH 'treeroot'
CALL apoc.cypher.run('MATCH (n:' + label + ') return n', null) YIELD value
RETURN value.n as node
You can use ANY function for apply reqular expression to labels:
match (n) where ANY(l in labels(n) WHERE l =~ ".*treeroot")
return n

Find connected groups over levels

A node A has 3 connected Nodes B1, B2, B3. Those Bx Nodes have again connected Nodes C1,C2,C3 and C4. Also Node A have 2 connected nodes C5 and C6.
Starting with node A I want to collect all C-nodes. I did a query for the A node, collect the two C-Nodes, then a query for the B-nodes, collect again all C-nodes and merge both arrays. Work but is not very clever.
I tried (Pseudocode)
MATCH (g)<-[:IS_SUBGROUP_OF*1]-(i)-[:HAS_C_NODES]->(c) WHERE g = A.uuid RETURN C_NODES
But I get either all c-nodes for A or for the B-nodes
How would I do a query that collects all C-Nodes starting with Node A?
* edited *
Here is some example data:
CREATE (a:A), (b1:B1), (b2:B2), (b3:B3), (c1:C1), (c2:C2), (c3:C3), (c4:C4), (a)-[r:HAS]->(c4), (a)-[r1:HAS]->(b1), (a)-[r2:HAS]->(b2), (a)-[r3:HAS]->(b3), (b1)-[r4:HAS]->(c1), (b1)-[r5:HAS]->(c2), (b2)-[r6:HAS]->(c3)
A query should return all nodes starting with C, no matter to which node they are connected (A or B).
You can add multiple labels for each node. You should use this to your advantage and segregate all the B and C nodes into a second label.
Eg:
CREATE (a:A), (b1:B1:BType), (b2:B2:BType), (b3:B3:BType), (c1:C1:CType), (c2:C2:CType), (c3:C3:CType), (c4:C4:CType), (a)-[r:HAS]->(c4), (a)-[r1:HAS]->(b1), (a)-[r2:HAS]->(b2), (a)-[r3:HAS]->(b3), (b1)-[r4:HAS]->(c1), (b1)-[r5:HAS]->(c2), (b2)-[r6:HAS]->(c3)
I have modified your create statement to group all the B nodes as :BType label and all the C nodes as :CType label.
You can simply use the optional match keyword to selectively traverse through the relationships if they exist and obtain the results you want.
match (a:A)-[:HAS]->(b:BType)-[:HAS]->(c:CType) optional match (a:A)-[:HAS]->(xc:CType) return c,xc
If you would like both sets of nodes to be grouped together you could try this statement instead which uses collect().
match (a:A)-[:HAS]->(b:BType)-[:HAS]->(c:CType) with a,collect (distinct c) as set1 optional match (a:A)-[:HAS]->(xc:CType) return set1 + collect (distinct xc) as output

neo4j/cypher: Find all nodes adjacent to all nodes in some set

Given a node, s, adjacent to a set, C, of >1 nodes of some label. I want to find all nodes that are also adjacent to every element in C.
More generally:
how does one define sets or groups in cypher?
how does one find nodes that are adjacent to all the nodes in a set?
Is this even doable in cypher?
Yes, absolutely, this is doable in cypher. Here is an example.
// start with finding the start node 's' and the adjacent nodes
match (s:Node {name: 's'} )-[:ADJ]->(C:Node)
// match only the adjacent nodes that have 'set C'
where C.set = 'C'
// pass C onto the remainder of the query
with s,C
// match the nodes that are adjacent to the nodes in 'set C'
match C-[:ADJ]->(adjacent)
// return all of the nodes in set C and a collection of the nodes
// adjacent to the set C nodes
return s.name, C.name, collect(adjacent.name)

Resources