There is a lot that can be improved in this query.
For starters, you're lacking indexes on :Compliant(text)
and :NonCompliant(text)
, without these the query is going to have terrible performance with that OPTIONAL MATCH patterns.
You can probably replace the top part (matching and collecting and unioning the text values) with this:
MATCH (g)
WHERE g:Compliant OR g:NonCompliant
WITH collect(DISTINCT g.text) AS uniqueNames
...
That said the approach for getting the number of edges between these nodes isn't optimal. Too many UNWINDs blowing up your cardinality. We can probably make this much easier.
If you're using Neo4j 4.1.x we can probably use UNION within a subquery so we can post-process results:
CALL {
MATCH (g:Compliant)<--(g2:Compliant)
WITH g, count(g2) as compliantEdges
RETURN g.text as text, compliantEdges, 0 as nonCompliantEdges
UNION ALL
MATCH (g:NonCompliant)<--(g2:NonCompliant)
WITH g, count(g2) as nonCompliantEdges
RETURN g.text as text, 0 as compliantEdges, nonCompliantEdges
}
RETURN text, sum(compliantEdges) as compliantEdges, sum(nonCompliantEdges) as nonCompliantEdges
If you're using an earlier version, you could leverage apoc.cypher.run()
from APOC Procedures instead:
CALL apoc.cypher.run("
MATCH (g:Compliant)<--(g2:Compliant)
WITH g, count(g2) as compliantEdges
RETURN g.text as text, compliantEdges, 0 as nonCompliantEdges
UNION ALL
MATCH (g:NonCompliant)<--(g2:NonCompliant)
WITH g, count(g2) as nonCompliantEdges
RETURN g.text as text, 0 as compliantEdges, nonCompliantEdges", {}) YIELD value
WITH value.text as text, value.compliantEdges as compliantEdges, value.nonCompliantEdges as nonCompliantEdges
RETURN text, sum(compliantEdges) as compliantEdges, sum(nonCompliantEdges) as nonCompliantEdges