Create a new relationship if any relationship exists in neo4j - 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.

Related

Create relationship between two existing nodes in STRUCTR.org

I created my database in "SCHEMA-Editor" from structr.org. I have two nodes "Project" and "ProjectManager" and relationship between these is "MEMBER".
I made a cypher query to create the graph like this:
MATCH (a:Project),(b:ProjectManager)
WHERE a.name = 'X' AND b.name = 'Y'
CREATE (a)-[r:MEMBER]->(b)
RETURN r,a,b;
And i expected to display the graph, but i got this message: "MEMBER.id must_not_be_empty"
Nodes and relationships created with Cypher are not immediately usable in Structr, because Cypher bypasses the Structr layer and acts directly on the database level. There are some extra steps that need to be done to make an object known to Structr: it needs an id attribute that contains a random UUID (universally unique identifier).
See "Tools" -> "Admin" -> "Relationships" -> "Add UUIDs" in the Schema Editor.
Additional tip: in Cypher, you should use MERGE instead of CREATE to avoid creating duplicate relationships between the two nodes (depending on your use-case).

How to use cypher to create a relationship between items in an array and another node

I would like to use cypher to create a relationship between items in an array and another node.
The result from this query was a list of empty nodes connected to each other.
MATCH (person:person),(preference:preference)
UNWIND person.preferences AS p
WITH p
WHERE NOT (person)-[:likes]->(preference) AND
p = preference.name CREATE (person)-[r:likes]->(preference)
Where person.preferences contains an array of preference names.
Obviously I am doing something wrong. I am new to neo4j and any help with above would be much appreciated.
Properties are attributes of a nodes while relationships involve one or two nodes. As such, it's not possible to create a relationship between properties of two nodes. You'd need to split the properties into their own collection of nodes, and then create a relationship between the respective nodes.
You can do all that in one statement - like so:
create (:Person {name: "John"})-[:LIKES]->(:Preference {food: "ice cream"})
For other people, you don't want to create duplicate Preferences, so you'd look up the preference, create the :Person node, and then create the relationship, like so:
match (preference:Preference {food: "ice cream"})
create (person:Person {name: "Jane"})
create (person)-[:LIKES]->(preference)
The bottom line for your use case is you'll need to split the preference arrays into a set of nodes and then create relationships between the people nodes and your new preference nodes.
One thing....
MATCH (person:person),(preference:preference)
Creates a Cartesian product (inefficient and causes weird things)
Try this...
// Get all persons
MATCH (person:person)
// unwind preference list, (table is now person | preference0, person | preference1)
UNWIND person.preferences AS p
// For each row, Match on prefrence
MATCH (preference:preference)
// Filter on preference column
WHERE preference.name=p
// MERGE instead of CREATE to "create if doesn't exist"
MERGE (person)-[:likes]->(preference)
RETURN person,preference
If this doesn't work, could you supply your sample data and noe4j version? (As far as I can tell, your query should technically work)

Create a relationship only if not exist in 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;

Neo4j- Avoid multiple relationships getting created between the same nodes in cypher?

I want to restrict the relationships getting created , if already created between the existing nodes. Right now its getting created multiple times? Is there any command similar to 'merge' for restricting duplicate relationships?Thanks for any suggestion
User MERGE instead of CREATE while creating relationships.
MERGE (Product)-[:listed_under_category]->(level3)
MERGE (level3)-[:child_of]->(level2)
hey i think the mix up but i need more information. Is that merge, merges the the whole statement. so if he does not find a "match" for the whole statement the database "creates" the whole statement.
So when you type something like merge (a)-[]->(b)-[]->(q)
if you already have (a)-[]->(b)
he will recreate (a)-[]->(b)-[]->(q) and you have in the db (a)-[]->(b)-[]->(q) , (a)-[]->(b)
but if you type merge (a)-[]->(b) merge(b)-[]->(q)
and you know that you have the nodes. Neo4j merge will create the relations if there are no relations. and match if there are relations
If I understand your question, CREATE UNIQUE may be the solution you are looking for. For example:
create (a:Ex {name: 'A'})-[r:inside]->(b:Ex {name: 'B'}) return a, b, r
sets up your original (a)-[]->(b) relationship. Then to extend the relationship in the manner you proposed ....
match (a)-[:inside]->(b) where a.name = 'A' and b.name = 'B'
create unique (a)-[:inside]->(b)-[:inside]->(q:Ex {name: 'Q'})
return a, b, q
CREATE UNIQUE also works if the relationships are different:
match (a)-[:inside]->(b) where a.name = 'A' and b.name = 'B'
create unique (a)-[:inside]->(b)-[:under]->(q:Ex {name: 'Q'})
return a, b, q
The MERGE clause also avoids duplicating relationships.

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!"

Resources