So basically I'm trying to create relationships in a network, based on information that is in other relationships. I've added an example to demonstrate what I'd like to achieve.
In this example I'm tracking users who have twitter accounts. There are two types of nodes:
Userwhich contains the labeluser_id(and some other stuff), generally has nothing to do with the twitter idSocialwhich represents a social network (for example Twitter if thenamelabel is 'twitter').
On top of that there are two types of relationships:
ACCOUNTwhich connectsUsertoSocialto denote whether someone has an account, this relationship also has the labelnameto represent the specific ID or name on that social networkFOLLOWSwhich can connect oneUser(u1) to anotherUser(u2) ifu1followsu2on Twitter.
The following three lines create three users with user_id 1 through 3 who all have a Twitter account, including the specific twitter id.
MERGE (u:User {user_id:'1', other_stuff:'...'}) MERGE (s:Social {name:'twitter'}) MERGE (u)-[:ACCOUNT {name:1111}]->(s)
MERGE (u:User {user_id:'2', other_stuff:'...'}) MERGE (s:Social {name:'twitter'}) MERGE (u)-[:ACCOUNT {name:2222}]->(s)
MERGE (u:User {user_id:'3', other_stuff:'...'}) MERGE (s:Social {name:'twitter'}) MERGE (u)-[:ACCOUNT {name:3333}]->(s)
So now I have a new piece of information: The person with twitter id 1111 follows another person with twitter id 5555.
So what has to happen:
- Find the user connected to Twitter with id
1111(This one always exists) - See if there is a user connected to Twitter who has an account with id
5555. If there's none then create a new one, set the Twitter relationship and set auser_idlabel on the node - Set a
FOLLOWSrelationship to indicate that1111is following5555
Initially I had the following cypher statment:
// Try to match against existing user node, or create new
MERGE (u1:User {user_id:'t5555'})
// Try to match against existing social node, or create new
MERGE (s:Social {name:'twitter'})
// Try to match against a user who has a twitter account '1111'
MERGE (u2:User)-[:Account {name:1111}]->(s)
// Try to add account for new user 5555
MERGE (u1)-[:Account {name:'5555'}]->(s)
// Try to find `FOLLOWS` relationship
MERGE (u2)-[:FOLLOWS]->(u1)
But that didn't really work right. I realized that I'm matching against user_id while I should only be matching against twitter account names in relationships.
A more recent try is the following:
MERGE (u1:User)-[:ACCOUNT {name:1111}]->(s1:Social {name:'twitter'})
MERGE (u2:User)-[:ACCOUNT {name:5555}]->(s2:Social {name:'twitter'})
MERGE (u1)-[:FOLLOWS]-(u2)
This does add a new node for the user u2 (though without user_id atm), but it also creates a new Social node. I sort of get why due to what is explained here, but there they assume that there is a label on the actual node to match against.
So what would be the right way to do this? Ideally in a way that I can always use the same statement. For example that after adding the fact that 1111 is following 5555 I can also add that 2222 is following 5555 without creating any unnecessary new nodes.
