Reputation: 41
Say I have a pizza menu where each type of pizza is represented as a node with label Pizza
, and each topping is a node with label Topping
. To get all the pizza's with pepperoni I write the following query
MATCH (p:Pizza)-[:HAS]->(t:Topping{type : "pepperoni"}) return p.
Then say I have a set of users who can specify their favorite pizzas.
MATCH (u:User)-[:HAS_FAVORITE]->(p:Pizza).
What is the best way to find the users who like ALL the pizzas having pepperoni ?
Thanks in advance for your time.
Upvotes: 1
Views: 360
Reputation: 41
The following method compares the count of the user's favorites having pepperoni with the count of all pizzas with pepperoni. It performs well because it matches using an index and relationship traversals to collect only user favorites having pepperoni. The answer posted by cybersam is slow because it has to do a full scan of all favorites.
MATCH (p:Pizza)-[:HAS]->(t:Topping { type : "pepperoni" })
WITH COUNT(p) AS pCnt, COLLECT(p) AS pCol
UNWIND pCol as pPep
MATCH (u:User)-[:HAS_FAVORITE]->(pPep)
WITH u, COUNT(*) as fCnt, pCnt
WHERE fCnt = pCnt
RETURN u
Upvotes: 2
Reputation: 67044
This is how to find all distinct users who like ANY pizza(s) with pepperoni topping:
MATCH (u:User)-[:HAS_FAVORITE]->(p:Pizza)-[:HAS]->(t:Topping {type : "pepperoni"})
RETURN DISTINCT u;
This is one way to find all distinct users who like ALL pizza(s) with pepperoni topping:
MATCH (p:Pizza)-[:HAS]->(t:Topping { type : "pepperoni" })
WITH COLLECT(p) AS ps
MATCH (u:User)-[:HAS_FAVORITE]->(q:Pizza)
WITH u, COLLECT(q) AS qs, ps
WHERE ALL (x IN ps WHERE x IN qs)
RETURN u;
Upvotes: 1