Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
12-26-2018 07:27 AM
Hi guys. I have couple of question. I'm newbie and i just started with neo4j and it's cypher.
This is how my db looks.
My question is: How query needs to look if i want to get all posts with all its data (post can have more than one picture, hashtag and to count how many likes and dislikes it has)?
If this is impossible is it better to get all posts with simple query and then for each post i get other data (one query for every relationship)? Is this approach bad and why?
Thank you in front guys
Solved! Go to Solution.
12-26-2018 04:23 PM
You can get what you need in the same query. We can use pattern comprehension to find potential matches and extract information from that into a list, or collect the nodes themselves if needed. We can also get the size() of a pattern using specific relationships to get the degree of those relationships (# of likes and dislikes).
For example:
MATCH (p:Post)<-[:POSTED]-(user)
RETURN p, [(p)-[:HAS_PICTURE]->(pic) | pic.URL] as picURLs, [(p)-[:HAS_HASHTAG]->(tag) | tag.Text] as hashtags, size ((p)<-[:LIKE]-()) as likes, size((p)<-[:DISLIKE]-()) as dislikes, user
12-26-2018 04:23 PM
You can get what you need in the same query. We can use pattern comprehension to find potential matches and extract information from that into a list, or collect the nodes themselves if needed. We can also get the size() of a pattern using specific relationships to get the degree of those relationships (# of likes and dislikes).
For example:
MATCH (p:Post)<-[:POSTED]-(user)
RETURN p, [(p)-[:HAS_PICTURE]->(pic) | pic.URL] as picURLs, [(p)-[:HAS_HASHTAG]->(tag) | tag.Text] as hashtags, size ((p)<-[:LIKE]-()) as likes, size((p)<-[:DISLIKE]-()) as dislikes, user
12-27-2018 08:57 AM
Thank you andrew. This helped me 🙂
12-28-2018 07:21 AM
I have one more question Andrew. Do you maybe know how would model look in c# if i want to return data in the way you said? Thank you again.
12-28-2018 08:59 AM
Do you know if performs better than doing OPTIONAL MATCH?
12-28-2018 10:08 AM
Shouldn't be a performance difference, pattern comprehension is like doing an OPTIONAL MATCH then a collect(). This is useful when you want to keep the original cardinality (number of rows) instead of increasing them with the OPTIONAL MATCH (or MATCH)
12-28-2018 10:35 AM
I need to do some more testing, but pattern comprehension is performing better interestingly. I've also noticed if within the pattern if I specify a label on the pattern vs. not, the execution plan was also vastly different. Whatever the explanation, just wanted to say thank you for introducing a new syntax to me!
OPTIONAL MATCH Strategy
Cypher version: CYPHER 3.4, planner: COST, runtime: SLOTTED. 351299 total db hits in 615 ms.
PROFILE
MATCH (otherProfile:Profile {profile_id: 123})-[otherProfileFavorite:FAVORITE]->(proj:Project)
WITH proj,
otherProfile.profile_id AS profile_id,
otherProfile.user_id AS user_id,
otherProfileFavorite.created_date AS created_date
ORDER BY created_date DESC
OPTIONAL MATCH ()-[rel:LIKE|FAVORITE|SHARE]->(proj)
WITH proj,
profile_id,
user_id,
created_date,
SUM(CASE Type(rel) WHEN "LIKE" THEN 1 ELSE 0 END) AS likeCount,
SUM(CASE Type(rel) WHEN "FAVORITE" THEN 1 ELSE 0 END) AS bmCount,
SUM(CASE Type(rel) WHEN "SHARE" THEN 1 ELSE 0 END) AS shareCount
OPTIONAL MATCH (authProfile:Profile {profile_id: 456})-[authProfile_r:LIKE|FAVORITE]->(proj)
RETURN proj.project_id AS project_id,
profile_id,
user_id,
created_date,
likeCount,
bmCount,
shareCount,
SUM(CASE Type(authProfile_r) WHEN "LIKE" THEN 1 ELSE 0 END) AS currentProfLiked,
SUM(CASE Type(authProfile_r) WHEN "FAVORITE" THEN 1 ELSE 0 END) AS currentProfBooked
ORDER BY created_date DESC
PATTERN COMPREHENSION Stragegy
Cypher version: CYPHER 3.4, planner: COST, runtime: SLOTTED. 8303 total db hits in 140 ms.
PROFILE
MATCH (otherProfile:Profile {profile_id: "123"})-[otherProfileFavorite:FAVORITE]->(proj:Project)
RETURN proj.project_id AS project_id,
otherProfile.profile_id AS profile_id,
otherProfile.user_id AS user_id,
otherProfileFavorite.created_date AS created_date,
size(()-[:LIKE]->(proj)) AS likeCount,
size(()-[:FAVORITE]->(proj)) AS bmCount,
size(()-[:SHARE]->(proj)) AS shareCount,
size((:Profile {profile_id: "456"})-[:LIKE]->(proj)) AS currentProfLiked,
size((:Profile {profile_id: "456"})-[:FAVORITE]->(proj)) AS currentProfBooked
ORDER BY created_date DESC
01-08-2019 02:23 AM
Thanks for this thread and the helpful and interresting answers provided. I do have a quick question following the use of Pattern Comprehension. I See that you can return values such as the picUrls in the example you provided. Is it possible to return a boolean based on the existence of a pattern in the return clause ?
I tried this but am not happy with the empty result
return [(p)-[:HAS_PICTURE]->() | true] as hasPic // true if relation exists and empty otherwise
I tried size also, wich is better as it returns 0 or an integer
return size((p)-[:HAS_PICTURE]->()) as hasPic // an int if relation exists and 0 otherwise
any way to get true / false ?
01-08-2019 12:48 PM
You can use exists()
to get a boolean for whether a pattern exists or not:
...
RETURN exists((p)-[:HAS_PICTURE]->())` as hasPic
01-09-2019 02:24 AM
So simple... Thanks.
All the sessions of the conference are now available online