Relationship not being applied correctly between nodes in Neo4j - neo4j

I am trying to run the code on this GraphGist to play with the Buendia Family Tree in Neo4j.
When I create two nodes and try to connect them with a relationship, as such:
CREATE (JoseArcadioBuendia:Male {name:'Jose Arcadio Buendia',Gender:'Male'})
then
CREATE (UrsulaIguaran:Female {name:'Ursula Iguaran',Gender:'Female'})
then
CREATE (JoseArcadioBuendia)-[:HUSBAND]->(UrsulaIguaran)
I get this:
Why is this code incorrect? The syntax looks fine and it appears to run for the author of the Gist. Am I doing something incorrectly?

I presume that you did not include all 3 CREATE clauses in a single query.
Cypher identifiers (like JoseArcadioBuendia and UrsulaIguaran) only exist for the life of a single query. The DB does not persist these identifiers. So, if you have a query that contains just CREATE (JoseArcadioBuendia)-[:HUSBAND]->(UrsulaIguaran)), neo4j would not know that the nodes already exist and would therefore create 2 new nodes for you (as well as the relationship).
If you had put all 3 clauses in a single query, you would have seen the results you expected. Otherwise, your query would first have to use MATCH to associate those identifiers with the proper nodes (similar to #Bond's answer).

The third line is incorrect. You are not specifying any nodes. Try the following:
MATCH (a:Male), (b:Female)
WHERE a.name = 'Jose Arcadio Buendia' AND b.name = 'Ursula Iguaran'
CREATE (a)-[:HUSBAND]->(b);

Related

In Neo4j how can I create relationships between one node an a collection of other nodes?

I have a graph containing some nodes with :SubSystem labels. I want to add a new node with a :Document label and create relationships with each of the existing :SubSystem nodes.
When I execute this statement:
MATCH (s:SubSystem)
CREATE (d:Document {title:'New Document'})
CREATE (d)-[:DEPICTS]->(s);
I was surprised when Neo4j created a new :Document node for each :SubSystem. I have 12 sub-systems, so I ended up with 12 new documents each related to one sub-system. I would have expected this behavior had I written:
MATCH (s:SubSystem)
CREATE (:Document {title:'New Document'})-[:DEPICTS]->(s);
But I was expecting that separating the CREATE clauses would create 1 document then create relationships between that document and each of the sub-systems.
Can someone explain why this doesn't work as I was expecting.
EDIT:
I found a solution. This statement does what I wanted, but I still think my original attempt should have worked.
CREATE (d:Document {title:'New Document'})
WITH d MATCH (s:SubSystem) CREATE (d)-[:DEPICTS]->(s);
A MATCH clause generates one or more result rows (or aborts the query if no results are found). A subsequent read/write clause would be executed once per row. Rearranging the order of the clauses, as you did, is one way to work around that (when possible).

Neo4j match node with Id and create relationship

I have a requirement to match two existing nodes with a specific Id and then create a relationship between these nodes.
Below is my cypher. But when I execute this , I always get no changes done .
MATCH(i:`Mechanical Component`)
where ID(i)=9912
with(i)
match(d:Features{name:"Mechanical Component"})
with(d)
where ID(d)=9934
MERGE (i)-[:FEATURES]->(d)
As Frank Pavageau said in the comments, you made an error in your query by not passing i with d in tha second WITHclause. Here is the corrected query you need:
MATCH(i:Mechanical Component)
where ID(i)=9912
with(i)
match(d:Features{name:"Mechanical Component"})
with(d,i)
where ID(d)=9934
MERGE (i)-[:FEATURES]->(d)
Keep in mind that using the internal id is really not recommended since it's generated and may change (see Should we use the Neo4J internal id?). You should probably use your own unique ID (with constraints) and match your node using this ID.

Why CREATE [relation] create 2 empty nodes in Neo4j?

I first create this 2:
CREATE (user1:Person {name:"User1"})
CREATE (user2:Person {name:"User2"})
And when I try
CREATE (user1)-[:FOLLOWS]->(user2)
It creates 2 empty nodes with no name nor anything related by the FOLLOW, but both nodes "User1"and "User2" are never blessed by my simple intention of relating them.
Why is this simple thing not working?
You are processing the statements separately. The user1 and user2 are identifiers that apply to a specific cypher statement. By the time you execute the last statement cypher no longer has a reference for user1 and user2.
You could write
match (u1:Person {name:"User1"}), (u2:Person {name:"User2"})
create (u1)-[:FOLLOWS]->(u2)
and that would find the nodes that you had previously created and join them with the :FOLLOWS relationship.
So when you just specified the identifiers int eh create statement it would match every node and join them.

How to create a relationship to existing nodes based on a condition of matching properties

In Neo4j, I am trying to load a CSV file whilst creating a relationship between nodes based on the condition that a certain property is matched.
My Cypher code is:
LOAD CSV WITH HEADERS FROM "file:C:/Users/George.Kyle/Simple/Simple scream v3.csv" AS
csvLine
MATCH (g:simplepages { page: csvLine.page}),(y:simplepages {pagekeyword: csvLine.keyword} )
MATCH (n:sensitiveskin)
WHERE g.keyword = n.keyword
CREATE (f)-[:_]->(n)
You can see I am trying to create a relationship between 'simplepages' and 'sensitiveskin' based on their keyword properties being the same.
The query is executing but relationships won't form.
What I hope for is that when I execute a query such as
MATCH (n:sensitiveskin) RETURN n LIMIT 25
You will see all nodes (both sensitive skin and simple pages) with auto-complete switched on.
CREATE (f)-[:_]->(n) is using an f variable that was not previously defined, so it is creating a new node (with no label or properties) instead, and then creating a relationship from that new node. I think you meant to use either g or y instead of f. (Probably y, since you don't otherwise use it?)

Adding relationship to existing nodes with Cypher

I'm trying out Neo4j for the first time. I'm using the 2.0-RC1 community edition.
I've created some nodes:
MERGE (u:User{username:'admin',password:'admin'})
MERGE (r1:Role{name:'ROLE_ADMIN'})
MERGE (r2:Role{name:'ROLE_WEB_USER'})
MERGE (r3:Role{name:'ROLE_REST_USER'})
and now I want to add relationships between the nodes. However, I don't want to clear out the existing database created with the script above, add the statements and run it again. I want to add relationships to the existing nodes. Google helped me find this:
START n=node(*), m=node(*)
where has(n.username) and has(m.name) and n.username = 'admin'
and m.name = 'ROLE_WEB_USER'
create (n)-[:HAS_ROLE]->(m)
Which works fine (even though I don't understand all the syntax). However, I am aware that this finds any node with a username property and any node with a name property, instead of using labels to check that it has the right type of node.
How can I do the same using labels?
In Neo4j 2.0 you can create schema indexes for your labels and the properties you use for lookup:
CREATE INDEX ON :User(username)
CREATE INDEX ON :Role(name)
To create relationships you might use:
MATCH (u:User {username:'admin'}), (r:Role {name:'ROLE_WEB_USER'})
CREATE (u)-[:HAS_ROLE]->(r)
The MATCH will use an index if possible. If there is no index, it will lookup up all nodes carrying the label and see if the property matches.
N.B. the syntax above will only work with Neo4j 2.0.0-RC1 and above.
Update as of 4/2020:
The new Cypher syntax is as follows. as 'CREATE INDEX ON' has been deprecated is..
CREATE INDEX FOR (n:Label) ON (n.property)

Resources