Create a relationship only if not exist in neo4j - neo4j

I want to add a relationship between two nodes, but only if the relationship does not exist. For example:
The Relationship between node1 and node2 currently exists with these properties: time:41221323,link:www.google.com
I am trying to add a relationship with different properties for example:
time:5344241,link:www.google.com
In this case i want to keep the original properties on the relationship.

You can use the below CQL query:
MATCH(a: startNodeLabel {attributes to match start node})
MATCH(m:endNodeLabel {attributes to match end node})
MERGE(a)-[:relationshipName]->(m)
The above merge statement creates relation between nodes a and m if there is no existing relationship between a and m.

You want either the MERGE or CREATE UNIQUE clause:
http://neo4j.com/docs/stable/query-merge.html
http://neo4j.com/docs/stable/query-create-unique.html
Also note that MERGE comes with additional ON CREATE SET and ON MATCH SET so you can control when properties get set.
I believe if you give either specific properties as part of the match syntax it will not create only if all of the properties match exactly.

Create Unique clause does serve this purpose. Neo4j Documet says
CREATE UNIQUE is in the middle of MATCH and CREATE — it will match
what it can, and create what is missing. CREATE UNIQUE will always
make the least change possible to the graph — if it can use parts of
the existing graph, it will.
START a=node(...), b=node(...)
CREATE UNIQUE (a)-[r:LIKES]-(b)
return a,b;

Related

Set Property of a Realtionship to label in Neo4j

I have a few Realtionships in Neo4J with the label "[r:Absatraction]". They all have a Property on them like "SysML:refine" or "SysML:trace" or "SysML:verify".
These "Abstractions connect differently labeled nodes. Now I want Neo4j to replace the Label "Abstraction" with the labels from the "SysML" Property. So that on the graph one can see "[r:refine],[r:verify]...".
I tried: apoc.create.addLabels, but it only seems to work for nodes.
Is there a way to do that?
In neo4j terminology, a relationship must have a single "type" -- not an optional set of "labels" (which are only for nodes). Furthermore, a relationship's type cannot be changed.
So, to do what you want, you'd have to create new relationships (with the desired types) and delete the old ones.
For example, here's is how you can use the APOC procedure apoc.create.relationship to create new relationships with the right types (and with the same properties as the old relationships except for SysML), and delete the old relationships:
MATCH (a:Foo)-[r:Abstraction]->(b:Foo)
CALL apoc.create.relationship(a, r.SysML, apoc.map.removeKey(PROPERTIES(r), 'SysML'), b) YIELD rel
DELETE r
RETURN rel
It is not possible to rename realtionships so one has to create a new one.
Example string for this problem:
match (a)-[old:Abstraction]->(b) where old.SysML = "Verify"
create (a)-[new:Verify]->(b)
delete old

Create a new relationship if any relationship exists in neo4j

How do I create a new relationship if any relationship exists?
In other words, how do I duplicate all relationships under a new type?
For example, starting with following data:
(A)-[knows]-(B)-[lives]-(house1)-[belongs_to]-(C)
I want to have added following relationships:
(A)-[some_rel]-(B)-[some_rel]-(house1)-[some_rel]-(C)
match (a)-[r]->(b) with a,b merge (a)-[:some_rel]->(b)
To "duplicate all relationships" (including their properties), you can do this:
MATCH (a)-[r1]->(b)
CREATE (a)-[r2:some_rel]->(b)
SET r2 = r1
The CREATE clause would even duplicate existing some_rel relationships. If you want to avoid that, then you can use MERGE instead.

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.

Making a relation in neo4j

I am not sure what I am doing wrong here, so here is how I create nodes
CREATE (urlnode_1:UrlNode {url:'url1', nodenumber:1})
CREATE (urlnode_2:UrlNode {url:'url2', nodenumber:2})
I create relations as follows
CREATE
(urlnode_1)-[:OutLink {anchor_text:['MY']}]->(urlnode_2)
Two nodes are created successfully first, now on running the code to create the relation, I would have liked the relation to exist between the two created nodes but it creates two new nodes say 3 and 4 and shows a relation between them. What am i doing wrong here?
To guide you the best way I can, let's sum up some Neo4j basics concerning node and relationships creation :
A node can have one or more labels, labels are meaned to group the nodes by domain (User, Speaker, Company, etc..see a label as a table name for e.g. ). A node can also have properties.
A relationship can have only ONE type, relationships are organizing the graph. Relationships can also have properties.
To create a node, you can use the CREATE writing clause :
CREATE (n:Person {firstname: 'John'})
The CREATE statement will not check if other nodes with same label and properties already exists, it will just create a new node
Relationships can also be created with the same clause :
MATCH (n:Person {firstname: 'John'}), (p:Person {firstname: 'Pierre'})
CREATE (n)-[:KNOWS]->(p)
A complete pattern can also be created in one go :
CREATE (n:Person {name:'Chris'})-[:KNOWS]->(p:Person {name:'Oliver'})
REMINDER : CREATE will not check for existing nodes.
--- AND NOW MERGE ---
MERGE will lazily check for existing nodes, see him as a MATCH OR CREATE clause :
MERGE (n:Person {firstname:'Fred'})
If the node with label Person and firstname Fred does not exist, the node will be created, otherwise nothing will happen. This is where come the handy ON MATCH and ON CREATE mentionned by #joslinm .
If you run this query multiple times after the node creation, your graph will not change, if you know the http protocol, you can say that MERGE is an indempotent request.
Be aware that, MERGE will ensure that an entire pattern exist in the database, by creating it if it does not already exist, meaning that if you do MERGE with a complete pattern, the entire pattern will be looked up for existence, not a single node :
Say a node with label Person and name property with value 'John' already exist in the db :
MERGE (n:Person {name:'John'})
will not affect the graph
However :
MERGE (n:Person {name:'John'})-[:KNOWS]->(:Person {name:'Nathalia'})
A new John node will be created, because the entire pattern does not exist.
It is recommended to use MERGE incrementally :
MERGE (n:Person {name:'John'})
MERGE (p:Person {name:'Nathalia'})
MERGE (n)-[:KNOWS]->(p)
If you want to know more about the MERGE clause, I can highly recommend you this wonderful article from Luanne on GraphAware : http://graphaware.com/neo4j/2014/07/31/cypher-merge-explained.html
Chris
If you create a relationship, a new one will get created every single time. They are not inherently unique. It sounds like you'd rather be merging the relationship; i.e., if they relationship is there, match it, if not, create it.
The merge syntax for it is as follows:
MERGE (a:Node)-[:LIKES]->(b:Node)
ON
MATCH SET a.msg = 'I matched!'
ON
CREATE SET a.msg = 'I created!'
RETURN a
You can try it out here: http://console.neo4j.org/
You'll notice that first the msg will be "I created!" then after it matches, it will be "I matched!"

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