I have the following graph structure in neo4j.
As you can see, there are two components in this graph. I want to retrieve the blue nodes (nodes of type NodeA
in the example) with their respective component. For the example, 4, 3, 2, 1
and 6, 5
.
I tried gcc
and wcc
of neo4j, however it failed, maybe I could not use it properly. Besides, I tried writing custom queries using cypher, however, my results were not even close to the result that I wanted.
You can simulate the graph with the following commands.
CREATE (a:NodeA {name: "1"});
CREATE (a:NodeA {name: "2"});
CREATE (a:NodeA {name: "3"});
CREATE (a:NodeA {name: "4"});
CREATE (a:NodeA {name: "5"});
CREATE (a:NodeA {name: "6"});
CREATE (b:NodeB {anotherName: "11"});
CREATE (b:NodeB {anotherName: "12"});
CREATE (b:NodeB {anotherName: "13"});
CREATE (b:NodeB {anotherName: "14"});
MATCH (a:NodeA {name: "1"})
MATCH(b:NodeB {anotherName: "11"})
CREATE (a) - [:CONTAINS] -> (b);
MATCH (a:NodeA {name: "2"})
MATCH(b:NodeB {anotherName: "11"})
CREATE (a) - [:CONTAINS] -> (b);
MATCH (a:NodeA {name: "3"})
MATCH(b:NodeB {anotherName: "11"})
CREATE (a) - [:CONTAINS] -> (b);
MATCH (a:NodeA {name: "3"})
MATCH(b:NodeB {anotherName: "12"})
CREATE (a) - [:CONTAINS] -> (b);
MATCH (a:NodeA {name: "4"})
MATCH(b:NodeB {anotherName: "12"})
CREATE (a) - [:CONTAINS] -> (b);
MATCH (a:NodeA {name: "5"})
MATCH(b:NodeB {anotherName: "13"})
CREATE (a) - [:CONTAINS] -> (b);
MATCH (a:NodeA {name: "5"})
MATCH(b:NodeB {anotherName: "14"})
CREATE (a) - [:CONTAINS] -> (b);
MATCH (a:NodeA {name: "6"})
MATCH(b:NodeB {anotherName: "14"})
CREATE (a) - [:CONTAINS] -> (b);
You can do it using the GDS strongly connected components procedure after projecting the relationships as undirected:
// Project the CONTAINS relationships as undirected so that traversals
// disregard the directions
CALL gds.graph.project(
'components',
['NodeA', 'NodeB'],
{CONTAINS: {orientation: 'UNDIRECTED'}}
);
// Only show the NodeA nodes using the node:NodeA label predicate
CALL gds.scc.stream('components', {})
YIELD nodeId, componentId AS component
WITH gds.util.asNode(nodeId) AS node, component
WHERE node:NodeA
RETURN node, component
ORDER BY component;
Results using your data:
+----------------------------------+
| node | component |
+----------------------------------+
| (:NodeA {name: "1"}) | 0 |
| (:NodeA {name: "2"}) | 0 |
| (:NodeA {name: "3"}) | 0 |
| (:NodeA {name: "4"}) | 0 |
| (:NodeA {name: "5"}) | 4 |
| (:NodeA {name: "6"}) | 4 |
+----------------------------------+