Hello Everyone,
I'm new to Neo4j and Cypher and am trying to formulate a Cypher query to count relationship directions between nodes of the same type. The brief background is that I have nodes of type Swc that can provide data to zero or more other Swcs. This is modelled using a PROVIDES relationship between node type Swc and itself. The direction of the relationship indicates which Swc provides the data and which one receives it.
I've loaded some Swc data from a CSV file and have some nodes as shown here:
I'm trying to write a query that returns the number of PROVIDES relationships in each direction for every Swc node. For the example above, the result for node CpApMySwc would be 3 INCOMING and 1 OUTGOING.
I've tried various Cypher queries but can't get the results I want. I can get the individual results using two separate queries of the form
MATCH (a:Swc)-[o:PROVIDES]->(b:Swc) WHERE a<> b RETURN a.name, count(o) as OUTGOING
but I'm sure it's possible to do so using just a single query. Another complication is that the relationship is optional for nodes: i.e. individual nodes may provide data OR receive it but not always both. Can anyone please suggest a solution? Thanks in advance for any help.
Regards,
Brendan
@brendan.jackman
your example cypher of
MATCH (a:Swc)-[o:PROVIDES]->(b:Swc) WHERE a<> b RETURN a.name, count(o) as OUTGOING
suggest that you are trying to eliminate a relationhip that points to itself, i.e. where a<b
as described at COUNT subqueries - Cypher Manual
match (a:Swc) return count { (a)-[:PROVIDES]-() } ;
which will return the number of :PROVIDES relationships regardless of direction that are attached to the :Swc node and point to another node of any label.
if you change to
match (a:Swc) return count { (a)-[:PROVIDES]->() } ;
this does the same except as a result of ->()
it is only counting outgoing relationships from a :PROVIDES relationship.
and
match (a:Swc) return count { (a)-[:PROVIDES]-(b:SWC) } ;
this does the same as the 1st query i provide but insures the resultant node has a :SWC label.
note for the 1st to examples i provide it is actually faster in the sense that for each node in graph it has metadata that reports # of relationships by type and direction. The 1st 2 queries would utilize the metadata. Whereas the 3rd would need to reach a :Swc node then iterate over each relationship, valiadate it is for :PROVIDES and then validate the destination is a :Swc labeled node
1 Like
Using what @dana_canzano taught you, you can try the following query:
match(n:Swc)
return
n.id,
count{(n)<-[:PROVIDES]-()} as incoming,
count{(n)-[:PROVIDES]->()} as outgoining
Test Data:
Results:
2 Likes
Hi @dana_canzano
Thank you so much for your quick response. I didn't realise how flexible COUNT is and your examples showed me better ways of structuring my queries. I've done some more research on COUNT subqueries now, so thanks again for all your help.
Kind regards,
Brendan
Hi Gary,
That's absolutely perfect! Thanks a million for that solution. I tested your elegant solution here and it works just fine. Exactly what I need. 
Kind regards,
Brendan
1 Like
Btw- I love the recently added subqueries: count (which @dana_canzano showed you), collect, and exists. You should look at these for your toolkit.
Other favorites of mine are pattern comprehension and map projections.
1 Like
One more, list comprehension.