Search code examples
neo4jcypher

Return a count of every edge type leaving a node in neo4j


Given a node with several types of outbound edges, let's say of types ["A","B","C"], how would I use cypher to query a neo4j database to return the counts of every edge.

E.g. if I have a graph like

(n0:NODE) -[:A]- (n1:NODE)
(n0:NODE) -[:A]- (n2:NODE)
(n0:NODE) -[:B]- (n3:NODE)
(n1:NODE) -[:B]- (n2:NODE)
(n4:NODE) // No edges

Assuming these edges are all bidirectional, I would want the query to return

Node, count(A), count(B), count(C) 
n0,   2,        1,        0
n1,   1,        1,        0
n2,   1,        1,        0
n3,   0,        1,        0 
n4,   0,        0,        0

For all nodes with label NODE.

I'm using this right now, which is okay, but it puts all the different edge types on different rows, so I have to iterate through all of them in post processing to build out the table that I want:

MATCH (n:NODE) -[r]- ()
WHERE 
    type(r) in ["A", "B", "C"]
RETURN 
    id(n) as nid,
    type(r) as rtype, 
    count(r) as cnt

Is there a way to get these all in one row like in my example?


Solution

  • There are several ways to go. Since you want to have all the types of the data even if it is 0, one option is:

    MATCH (n:NODE)
    OPTIONAL MATCH (n)-[r]-(m:NODE)
    WHERE 
        type(r) IN ["A", "B", "C"]
    WITH 
        CASE type(r) WHEN 'A' THEN 1 ELSE 0 END AS cA, 
        CASE type(r) WHEN 'B' THEN 1 ELSE 0 END AS cB,
        CASE type(r) WHEN 'C' THEN 1 ELSE 0 END AS cC,
        n.key AS Node
    RETURN Node, SUM(cA) AS countA, SUM(cB) AS countB, SUM(cC) AS countC
    

    Which for sample data:

    MERGE (n0:NODE {key:'n0'})
    MERGE (n1:NODE {key:'n1'}) 
    MERGE (n2:NODE {key:'n2'}) 
    MERGE (n3:NODE {key:'n3'}) 
    MERGE (n4:NODE {key:'n4'})    
    
    MERGE(n0)-[:A]-(n1)
    MERGE(n0)-[:A]-(n2)
    MERGE(n0)-[:B]-(n3)
    MERGE(n1)-[:B]-(n2)
    

    Returns:

    ╒══════╤════════╤════════╤════════╕
    │"Node"│"countA"│"countB"│"countC"│
    ╞══════╪════════╪════════╪════════╡
    │"n0"  │2       │1       │0       │
    ├──────┼────────┼────────┼────────┤
    │"n1"  │1       │1       │0       │
    ├──────┼────────┼────────┼────────┤
    │"n2"  │1       │1       │0       │
    ├──────┼────────┼────────┼────────┤
    │"n3"  │0       │1       │0       │
    ├──────┼────────┼────────┼────────┤
    │"n4"  │0       │0       │0       │
    └──────┴────────┴────────┴────────┘
    

    *Note that your approach in the question, will not return "n4" as it has no relationships and your query only match nodes with a relationship.