Reputation:
Cypher newbie here.
I made this graph of tagged Media using the code below.
CREATE
(funny:Tag { name: 'Funny' }),
(sad:Tag { name: 'Sad' }),
(movie:Tag { name: 'Movie' }),
(tv:Tag { name: 'TV Show' }),
(hangover:Media { name: 'The Hangover' }),
(koth:Media { name: 'King of the Hill' }),
(simpsons:Media { name: 'The Simpsons' }),
(twm:Media { name: 'Tuesdays with Morrie' }),
(mm:Media { name: 'Mary & Max' }),
(funny)-[:DESCRIBES]->(hangover),
(funny)-[:DESCRIBES]->(koth),
(funny)-[:DESCRIBES]->(simpsons),
(sad)-[:DESCRIBES]->(twm),
(sad)-[:DESCRIBES]->(mm),
(movie)-[:DESCRIBES]->(hangover),
(movie)-[:DESCRIBES]->(twm),
(movie)-[:DESCRIBES]->(mm),
(tv)-[:DESCRIBES]->(koth),
(tv)-[:DESCRIBES]->(simpsons)
What I want to do is group Tags together into Contexts, such that one Context node has the same meaning as multiple Tags.
MATCH
(tf:Tag { name: 'Funny' }),
(tr:Tag { name: 'Sad' }),
(tm:Tag { name: 'Movie' })
(tt:Tag { name: 'TV Show' })
CREATE
(fm:Context { name: 'Funny Movies' }),
(ft:Context { name: 'Funny TV' }),
(s:Context { name: 'Sad Movies' }),
(fm)-[:INCLUDES]->(tf),
(fm)-[:INCLUDES]->(tm),
(ft)-[:INCLUDES]->(tf),
(ft)-[:INCLUDES]->(tt),
(s)-[:INCLUDES]->(tm),
(s)-[:INCLUDES]->(tr)
So now we have this thing.
I want to take a Context node and get Media such that ALL Tags in that Context describe each returned Media.
I tried MATCH (c:Context { name: 'Funny Movies' })-[:INCLUDES]->()-[:DESCRIBES]->(m) RETURN m
to match media tagged with both Funny
and Movies
. The expected output was only The Hangover
, but I get all Media instead.
It's pretty obvious that I don't understand the kind of query I need to write. What is wrong with my query, and how can I produce the output that I want?
Upvotes: 0
Views: 139
Reputation: 29172
You can use the bi-directional pattern:
MATCH (c:Context { name: 'Funny Movies' })-[:INCLUDES]->()-[:DESCRIBES]
->(m)<-
[:DESCRIBES]-()<-[:INCLUDES]-(c)
RETURN m
Upvotes: 0
Reputation: 20185
When you start from a context, you can collect
the tags and then match movies that are related to ALL
the tags. The highlighted words in the previous sentence are the keywords for you as reference in the neo4j documentation :
MATCH (c:Context {name:"Funny Movies"})-[:INCLUDES]->(tag)
WITH collect(tag) AS tags
MATCH (m:Media) WHERE ALL( x IN tags WHERE (x)-[:DESCRIBES]->(m))
RETURN m
Upvotes: 2