Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
06-21-2021 08:05 AM
I want to create FOLLOW relationship between multiple Users in my database who have rated any movie. I have no idea how to do this with a single and simple query. I tried the following query and it simply failed with some JAVA Heap Space error.
MATCH (m1:Movie)<-[r1:RATED]-(elisha:User), (m2:Movie)<-[r2:RATED]-(garfield:User),(m3:Movie)<-[r3:RATED]-(hermann:User),(m4:Movie)<-[r4:RATED]-(lester:User),
(m5:Movie)<-[r5:RATED]-(casper:User),(m6:Movie)<-[r6:RATED]-(lester:User),
(m7:Movie)<-[r7:RATED]-(alaa:User),(m8:Movie)<-[r8:RATED]-(jake:User),
(m9:Movie)<-[r9:RATED]-(odie:User),(m10:Movie)<-[r10:RATED]-(pink:User)
CREATE (elisha)-[:FOLLOW]->(garfield),
(garfield)-[:FOLLOW]->(hermann),
(garfield)-[:FOLLOW]->(lester),
(lester)-[:FOLLOW]->(elisha),
(casper)-[:FOLLOW]->(pink),
(alaa)-[:FOLLOW]->(jake),
(jake)-[:FOLLOW]->(garfield),
(jake)-[:FOLLOW]->(odie)
![graph|625x249](upload://cAJlkhPM2wSm6ALo6Ob4QvZbx9R.jpeg)
06-21-2021 10:24 AM
Not really clear what the goal of the cypher is however your usage of MATCH
is going to result in a cartesian join and thus not surprising you get an out of heap error. For example your statement of
MATCH
(m1:Movie)<-[r1:RATED]-(elisha:User),
(m2:Movie)<-[r2:RATED]-(garfield:User),
(m3:Movie)<-[r3:RATED]-(hermann:User),
(m4:Movie)<-[r4:RATED]-(lester:User),
(m5:Movie)<-[r5:RATED]-(casper:User),
(m6:Movie)<-[r6:RATED]-(lester:User),
(m7:Movie)<-[r7:RATED]-(alaa:User),
(m8:Movie)<-[r8:RATED]-(jake:User),
(m9:Movie)<-[r9:RATED]-(odie:User),
(m10:Movie)<-[r10:RATED]-(pink:User)
...
......
.........
is such that if (m1:Movie)<-[r1:RATED]-(elisha:User),
returns 100 paths and (m2:Movie)<-[r2:RATED]-(garfield:User)
returns 5 paths then the first 2 lines will then result in 500 paths. But as this continues for m2
through m9
then presumably the cartesian will get very very large.
Also each of those 8 statements above simply matches a :Movie
to a :User
via a :RATED
relationship and does it 8 times. So in effect line 2 above will return the same number of paths as line 3 and line 4 and line 5.... all the way to line 9
06-21-2021 10:30 AM
I have attached the image in comment. Hope you can see it. I want to create a FOLLOW relation between multiple nodes of type "User". The problem is that, I cannot match them directly using username without using the "rated" relation and the "rated " relation cannot be used without mentioning movies. Is there a way to achieve the FOLLOW relation between nodes which are part of a rated relation? Is there a way to make them FOLLOW each other without using "MOVIES" and "rated" ?
06-21-2021 03:34 PM
Yes, it's possible to MATCH to them and link them, but what's missing is what logic we're supposed to use to get the output graph you provided. The users are not all interconnected, there's some kind of logic being applied here to get this specific graph, but you haven't told us what it is.
06-22-2021 01:37 AM
The logic is that both rated at least one movie. i.e. (Elisha:User)- [:r1:rated]-> m1:Movie and same for all other users. Without mentioning movie rating relationship, it will not let us directly get access to these users (I tried before and it didn't work). What has worked for me so far is following code :
> MATCH (m1:Movie)<-[r1:RATED]-(u1:User), (m2:Movie)<-[r2:RATED]-(u2:User)
> where u1.username ="Elisha" and u2.username="Pink"
> CREATE (u1)-[r3:FOLLOW {Year:2021}]->(u2)
But this only works for one relation between two users. I will have to do it separately for each relation but that would need me to use Create again and again. I want to achieve it with a single create.
06-22-2021 10:49 AM
If you need the cross product of all users who have rated any movie, then this should work
MATCH (u:User)
WHERE (u)-[:RATED]->(:Movie)
WITH collect(u) as users
UNWIND users as u1
UNWIND users as u2
WITH u1, u2
WHERE id(u1) < id(u2)
CREATE (u1)-[r3:FOLLOW {Year:2021}]->(u2)
The WHERE id(u1) < id(u2)
is to prevent mirrored results, where we consider the same two users except with their places switched. It also prevents considering a user with themselves.
If you need to create a linked list between them instead, then from the collected users you could make an APOC call like apoc.nodes.link()
to create a single path that runs through them all.
As mentioned before, this is used to consider the cross product of users, but your output graph isn't the result of a cross product, there is some other logic dictating how the users and connected and which ones are connected and which aren't, and that isn't something that's been shared yet.
All the sessions of the conference are now available online