cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

How to filter only on nodes with edges

I have a DSL for querying the graph which looks like this:
Graph.query(country: { value: 'Italy' , value: 'Spain', value: 'Greece' }, movie: { title: 'Matrix' })

and produces this cypher query, which works fine:

MATCH (m:Movie)<-[:ACTED_IN]-(a:Actor)
WHERE m.title = 'Matrix'
WITH collect(a) as actors, m as movie
UNWIND actors as actor
WITH DISTINCT actor, movie
MATCH (movie)<-[:DIRECTED_BY]-(d:Director)
WHERE (movie)<-[:AVAILABLE_IN]-(c0:Country { value: 'Italy' })
AND (movie)<-[:AVAILABLE_IN]-(c1:Country { value: 'Spain' })
AND (movie)<-[:AVAILABLE_IN]-(c2:Country { value: 'Greece' })
RETURN actor.name, d.name, movie.title

Question: in rare cases a Country node, for example Spain, will have no edges, and as such currently the above cypher query would rightly return no results. But is it possible to rewrite the query above so that it would ignore the Country node if it has no edges, matching and returning nodes that are connected to the remaining initially defined list of countries i.e. Italy, Greece?

Thanks

2 REPLIES 2

You could add it as an OPTIONAL MATCH clause after your MATCH
(movie)<-[:AVAILABLE_IN]-(c1:Country { value: 'Spain' })

OR

Maybe you can use some predicate functions like all, any, etc.
Available in the Cypher manuel

OR you can combine OPTIONAL MATCH with WHERE and remove the WHERE from your first clause.

MATCH (m:Movie)<-[:ACTED_IN]-(a:Actor)
WHERE m.title = 'Matrix'
WITH collect(a) as actors, m as movie
UNWIND actors as actor
WITH DISTINCT actor, movie
MATCH (movie)<-[:DIRECTED_BY]-(d:Director)
OPTIONAL MATCH (movie)<-[:AVAILABLE_IN]-(c:Country) WHERE c.value IN ['Italy', 'Spain', 'Greece']
RETURN actor.name, d.name, movie.title

Beware the OPTIONAL MATCH will be repeated for each Director of a movie.
OPTIONAL MATCH will not remove any row, including when the country is null

Tried OPTIONAL MATCH with WHERE and it works for this use case, however it returns incorrect results for other more complex queries because of WHERE ... IN filtering. I think what I need is to take all of the Country nodes that have edges connecting them to a Movie and then do a WHERE ... AND operation - is that possible?