Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
07-18-2020 10:14 AM
Hi,
I’m really new to NEO4J and currently testing some simple Cypher queries.
I want to model users and their hobbies, where one user can have multiple hobbies.
Users and their hobby are created as nodes with the respective labels :User and :Hobby.
I can easily find users that are doing the hobby “Sport” or “Music”:
MATCH (u:User)-[:HAS_HOBBY]->(h:Hobby)
WHERE h.name = "Sport" OR h.name = "Music"
RETURN u
Result: Max, Joe
But how can I find users that are doing both the hobbies “Sport” AND “Music”?
In this case the query should only return the user “Max”.
Many thanks for your help.
07-18-2020 10:26 AM
Hello @drjonniex and welcome to the Neo4j community
Try:
MATCH (u:User)-[:HAS_HOBBY]->(h:Hobby)
WITH u, collect(DISTINCT h.name) AS hobbies
WHERE all(x IN hobbies WHERE x IN ["Sport", "Music"])
RETURN u
Regards,
Cobra
07-18-2020 10:54 AM
Many thank's for your quick and very helpful answer!
07-18-2020 11:07 AM
match (a:User)-[:HAS_HOBBY]->(b:Hobby)
where b.name = "Sport"
match (a)-[:HAS_HOBBY]->(c:Hobby)
where c.name = "Music"
return a
returns Max
07-20-2020 12:45 AM
I expanded the example graph from above and added the additional hobby "Dancing" for "Max":
The query suggestion from @Cobra seems not work in this case
MATCH (u:User)-[:HAS_HOBBY]->(h:Hobby)
WITH u, collect(DISTINCT h.name) AS hobbies
WHERE all(x IN hobbies WHERE x IN ["Sport", "Music"])
RETURN u
Result: Joe
As i can understand the query the result seems to be logical. The hobby Sport from user Joe
satisfies
x IN hobbies WHERE x IN ["Sport", "Music"]
and because the user Joe has only one hobby the all predicate is also fulfilled.
The query suggestion from @ameyasoft works and only the user Max is returned.
But the disadvantage is that you have to use a variable name for every hobby
in the query.
I am particularly thinking about how the query can be easily and dynamically constructed when the hobby filter comes from some sort of user interface. The user can select several hobbies via a checkbox.
07-20-2020 01:08 AM
Hi,
MATCH (u:User)-[:HAS_HOBBY]->(h:Hobby)
WITH u, collect(DISTINCT h.name) AS hobbies
WHERE all(x IN ["Sport", "Music"] WHERE x IN hobbies)
RETURN u
07-22-2020 12:37 AM
Many thanks.
I would like to use the query syntax from @Cobra to combine multiple filters at once.
For example, to further narrow down the user result set by character details.
It seems to be pretty easy with the query syntax:
MATCH (u:User)-[:HAS_HOBBY]->(h:Hobby)
WITH u, collect(DISTINCT h.name) AS hobbies
WHERE all(x IN ["Sport", "Music"] WHERE x IN hobbies)
WITH u
MATCH (u)-[:HAS_CHARACTER]->(c:CharacterDetail)
WITH u, collect(DISTINCT c.name) AS cdetails
WHERE all(x IN ["Calm", "Spontaneous"] WHERE x IN cdetails)
WITH U
*** NEXT FILTER ***
WITH U
*** NEXT FILTER ***
RETURN u
Are there any performance considerations by applying multiple filters at once
on databases with a large amount of user nodes?
As I understand it would be necessary to create an index on the name property for the
Hobby and CharacterDetail nodes.
07-22-2020 12:43 AM
Normally, indexes are useful when they are directly specified in the WHERE
clause, for example: n.id = 0
. In your case, you already collected the name for each nodes so I don't think there will be any improvments but you can still try
You could also use subquery with UNION
All the sessions of the conference are now available online