Check whether a node exists, which has relation to all given nodes

Say we have some data like this:

create
(a:Person{name:'andy'})-[:LIKES]->(:Animal{name:'cat'}),
(b:Person{name:'bob'})-[:LIKES]->(:Animal{name:'cat'}),
(c:Person{name:'charlie'})-[:LIKES]->(:Animal{name:'cat'}),
(a)-[:LIKES]->(:Animal{name:'dog'}),
(b)-[:LIKES]->(:Animal{name:'dog'})

I would like to know which Person has identical LIKES as andy, if there is any such Person. Andy likes 'cat' and 'dog', so Bob should appear, but not Charlie because he doesn't like 'dog'.

How can I form such query? i'd like the query to work with many LIKES, so in the future when there are 100 animals, I can still find someone with identical taste as andy.

I've tried something like this

match
(p:Person{name:'andy'})-[:LIKES]->(a:Animal),
(a)<-[:LIKES]-(p2:Person)
return p,a,p2

But this would return Charlie as well.

Here's a knowledge base article on performing match intersection which should give you some options for doing this.

1 Like

Thanks for the reply Andrew! This was exactly what I was looking for!

Apologies if this is asking too much, but could you please help me with another similar problem I'm facing?

I have a service where users answer a question by a scale of 1~4.
I'd like to find a user with identical answers to myself.

Questions and answers are stored like this:

create
(q:Question{questionId: randomUUID(), text: 'How much do you like dogs on scale 1~4'}),
(q)<-[:BELONGS_TO]-(a1:Answer{choice:1}),
(q)<-[:BELONGS_TO]-(a2:Answer{choice:2}),
(q)<-[:BELONGS_TO]-(a3:Answer{choice:3}),
(q)<-[:BELONGS_TO]-(a4:Answer{choice:4})

return count(q) as c // (Just to verify that the write transaction worked)

Here's answering the question:

match
(q:Question{questionId:'someId'})-[:BELONGS_TO]-(a:Answer{choice:1}),
(u:User{userId:'someId'})
create
(u)-[ch:CHOSE]->(a)

return count (ch) as c

This is the query I have at the moment to get identical answered users:

MATCH (u:User{userId:"someId"})-[:CHOSE]->(a:Answer)
WITH collect(a) as answers
WITH head(answers) as head, tail(answers) as answers
MATCH (u2:User)-[:CHOSE]-(head)
WHERE ALL(answer in answers WHERE (e2)-[:CHOSE]-(answer))
return u2

Would you suggest any other way to store question/answer?
It's my first time with neo4j, so any suggestion would be greatly appreciated.