user305883
user305883

Reputation: 1741

Simple query in neo4j - no record if a node has degree 0

To better understand how results are formatted in neo:

A simple query where node ENSG00000180447 has no neighbor:

MATCH (d:Target)-[r:Interaction]-(t:Target)
        where d.uid = 'ENSG00000180447'
        with d, count(t) as degree
        Return d, degree

(no changes, no records)

Instead

MATCH (d:Target)
        where d.uid = 'ENSG00000180447'
        Return d # return the node

MATCH (d:Target)-[r:Interaction]-(t:Target)
        where d.uid = 'ENSG00000180447'
        with count(t) as degree
        Return degree # return 0

I would like to get returned node and its degree on the same query. What is it wrong with the first query?

Upvotes: 0

Views: 886

Answers (2)

InverseFalcon
InverseFalcon

Reputation: 30407

The problem, as stdob-- points out, is that when you perform a MATCH, it only returns rows for which the match is true. So you're asking for a match between that one specific node to a :Target node using a relationship of type :Interaction. Since no such pattern exists, no rows are returned.

The SIZE() function will probably be your best bet for a concise query, you can use it to find the occurrences of a pattern. In this case, we can use it to find the number of relationships of that type to a :Target node:

MATCH (d:Target)
WHERE d.uid = 'ENSG00000180447'    
RETURN d, SIZE( (d)-[:Interaction]-(:Target) ) AS degree

EDIT - explaining why your query returning the node and count returns no rows.

COUNT() is an aggregation that only has context from the non-aggregation columns (grouping key). On its own, COUNT() has no other context and no grouping keys, and it can handle null values:

COUNT(null) = 0.

When we perform MATCHes, we build up rows. Where a MATCH doesn't find any matches, no rows are returned:

MATCH (ele:PinkElephant)
RETURN ele
// (no changes, no records)

When we try to pair this with aggregation, we will still get no rows, because the aggregation will run for every possible row, but there are no rows to execute on:

MATCH (person:Person)-[:Halucinates]->(ele:PinkElephant)
RETURN ele, COUNT(person)
// (no changes, no records)

In this case, you're asking for rows of :PinkElephant nodes, and for each of those nodes, a count of the people who hallucinate that pink elephant.

But there are no :PinkElephant nodes. There are no rows present for COUNT() to operate on. We can't show any rows because there are no nodes present to populate them.

Even if there WERE :PinkElephant nodes in the graph, if there were no relationships to :People nodes, the result would be the same. The match would find nothing, because the pattern you asked for (pink elephants that are hallucinated by people) doesn't exist. There are no :PinkElephants that are hallucinated by a :Person, so no nodes to populate the ele column, so no rows, and if there are no rows, your COUNT() has nothing to execute on, and no place to add a return value.

Upvotes: 0

stdob--
stdob--

Reputation: 29147

"MATCH" is looking for the exact pattern match, and does not find it for the node with the uid = 'ENSG00000180447'. Two ways:

1) Use OPTIONAL MATCH:

MATCH (d:Target)
        WHERE d.uid = 'ENSG00000180447'    
OPTIONAL MATCH (d)-[r:Interaction]-(t:Target)
RETURN d, COUNT(t) AS degree

2) Use zero length paths:

MATCH (d:Target)-[r:Interaction*0..1]-(t:Target)
        where d.uid = 'ENSG00000180447'
        with d, count(t) as degree
        Return d, degree-1

Upvotes: 1

Related Questions