Neo4j create graph that some nodes have more than one relationships - neo4j

Over my Neo4j I want to create this graph:
SO I tried to create some nodes and relationships with:
MERGE (D:POINT {NAME:'d'})<-[:LINKS]-(A:POINT {NAME:'a'})-[:LINKS]->(B:POINT {NAME:'b'})-[:LINKS]->(C:POINT {NAME:'c'})
But I cannot find out how I will create the relationships between D and B points also I cannot find out how I will link the A and C as well.
Do you have any Idea how to do that?

In order to avoid unintentionally creating duplicate nodes and/or relationships, you must invoke MERGE on individual nodes and relationships.
To quote the dev manual:
When using MERGE on full patterns, the behavior is that either the
whole pattern matches, or the whole pattern is created. MERGE will not
partially use existing patterns — it’s all or nothing. If partial
matches are needed, this can be accomplished by splitting a pattern up
into multiple MERGE clauses.
For example, to properly create your graph without any duplicate nodes or relationships:
MERGE (A:POINT {NAME:'a'})
MERGE (B:POINT {NAME:'b'})
MERGE (C:POINT {NAME:'c'})
MERGE (D:POINT {NAME:'d'})
MERGE (A)-[:LINKS]->(B)
MERGE (A)-[:LINKS]->(C)
MERGE (A)-[:LINKS]->(D)
MERGE (B)-[:LINKS]->(C)
MERGE (D)-[:LINKS]->(B)

CREATE seems to be the natural way to me for creating nodes and relationships.
CREATE (D:POINT {NAME:'d'})<-[:LINKS]-(A:POINT {NAME:'a'})
, (A)-[:LINKS]->(B:POINT {NAME:'b'})<-[:LINKS]-(D)
, (B)-[:LINKS]->(C:POINT {NAME:'c'})<-[:LINKS]-(A)

You can do it by doing a MATCH before a MERGE eg. FOR the relationship between A and D do:
MATCH (A:POINT {NAME:'a'}),(B:POINT {NAME:'d'}) MERGE (A)-[:LINKS]->(B)

Related

Neo4j: Multiple Relationships Merge Issue

I've a neo4j schema in which I've 3 nodes. e.g. p,b,c
I want to write a Merge query such that
MERGE (p)-[:has_b]->(b),
MERGE (p)-[:has_c]->(c1),
MERGE (p)-[:has_c]->(c2)
where c1 and c2 are instance of c node having different property values.
i.e. Merge on all three relationships.
If any of 3 merge queries creates a new node, all relationships should use newly created p node.
I can achieve this if I had only two relationships using
(c)<-[:has_c]-MERGE (p)-[:has_b]->(b)
Any suggestions how to do it for 3 relationships as in my case?
FYI, I'm using py2neo which isn't helping at all.
Nodes don't have instances. A node is a node and it has a label.
You can MERGE your nodes first to make sure they exist and that all relationships use the same p:
MERGE (p:LabelA {k: "v"})
MERGE (b:LabelB {k: "v"})
MERGE (c1:LabelC {k: "v"})
MERGE (c2:LabelC {k: "v"})
MERGE (p)-[:has_b]->(b)
MERGE (p)-[:has_c]->(c1)
MERGE (p)-[:has_c]->(c2)
This will create the nodes and relationships only once.

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.

Cant use Merge inside foreach for existed nodes

I am expecting he following query to create nodes (only if exits) and relations by a given source node (1) and a list(2) this way:
MERGE (p1:C9{userId: '1'}) WITH p1, [{userId:"2"}] AS users
FOREACH (user IN users | MERGE
((p1)-[r1:follow]->(:C9 {userId: user.userId})))
Thats the outcome:
Now if I am executing this query again by switching the node id's this way:
MERGE (p1:C9{userId: '2'}) WITH p1, [{userId:"1"}] AS users
FOREACH (user IN users | MERGE
((p1)-[r1:follow]->(:C9 {userId: user.userId})))
We got this:
neo4j duplicated for me the node with id=1. I want it to merge in case of existed nodes.
I expected to see only two nodes connected to each other by merging existed nodes.
any idea what I should fix?
Thanks,
ray.
I normally avoid FOREACH when I can use an UNWIND, so I would start with something like this:
MERGE (p1:C9 {userId: '1'})
WITH p1, [{userId:"2"}] AS users
UNWIND users AS user
MERGE (p1)-[r1:follow]->(:C9 {userId: user.userId})
Sometimes you also want to separate your node creation from your relationship creation. If you do both at the same time, I think that Neo4j can think that you want a unique combination of node (with properties) and relationship.
MERGE (p1:C9 {userId: '1'})
WITH p1, [{userId:"2"}] AS users
UNWIND users AS user
MERGE (p2:C9 {userId: user.userId})
MERGE (p1)-[r1:follow]->(p2)
You can use MERGE within FOREACH.
But you have to understand the semantics of MERGE. It tries to MATCH a full pattern and if it does not find it it will fully CREATE that pattern.
You in your case you try to find a pattern within the context of p1 and not globally and if not found it will create it within the context of p1.
So if you change your query to:
MERGE (p1:C9{userId: '2'})
WITH p1, [{userId:"1"}] AS users
FOREACH (user IN users |
MERGE (p2:C9 {userId: user.userId})
MERGE (p1)-[r1:follow]->(p2)
)
I.e. create p2 first and then MERGE the relationship, it will work.

Neo4j - Cypher query to import category tree without duplicate entry

I have three independent category trees that is going to import at any order using cypher.
(c2)-[PARENT]->(c1)
(c4)-[PARENT]->(c3)->[PARENT]->(c1)
(c5)-[PARENT]->(c3)
and need to create the structure mentioned in the figure using the query . The query I written is
MERGE (:Category {name:'c2'})-[:PARENT]->(:Category {name:'c1'})
MERGE (:Category {name:'c4'})-[:PARENT]->(:Category {name:'c3'})-[:PARENT]->(:Category {name:'c1'})
MERGE (:Category {name:'c5'})-[:PARENT]->(:Category {name:'c3'})
But above query creating duplicate category c1 for second merge query which I need to avoid . Also the third query should create new category c3 which is happening correctly now.
One more thing is that these three cypher query should be independently executable .eg: System already have a category tree (c2)-[PARENT]->(c1) and need to add (c4)-[PARENT]->(c3)->[PARENT]->(c1) in to the category tree using cypher.
I can go with some similar approach mention in the documentation
http://neo4j.com/docs/stable/cypherdoc-linked-lists.html . but just want to check is there a simple way to solve this problem
Try this (without typo in third query)
MERGE (:Category {name:'c2'})-[:PARENT]->(c1:Category {name:'c1'})
MERGE (:Category {name:'c4'})-[:PARENT]->(:Category {name:'c3'})-[:PARENT]->(c1)
MERGE (:Category {name:'c5'})-[:PARENT]->(:Category {name:'c3'})
You can use single query to avoid duplicate entry
MERGE (:Category {name:'c4'})-[:PARENT]->(:Category {name:'c3'})-[:PARENT]->(:Category {name:'c1'})<-[:PARENT]-(:Category {name:'c2'})
MERGE (:Category {name:'c5'})-[:PARENT]->(:Category {name:'c5'})
I solve the problem by adding one more label called Root for the top level category .
Cypher query for first tree - (c2)-[PARENT]->(c1)
MERGE (nc1:Category:Root{name:'c1'})
MERGE (nc3:Category {name:'c2'})-[:PARENT]->(nc1)
Cypher query for second tree - (c4)-[PARENT]->(c3)->[PARENT]->(c1)
MERGE (nc1:Category:Root{name:'c1'})
MERGE (nc3:Category {name:'c3'})-[:PARENT]->(nc1)
MERGE (:Category {name:'c4'})-[:PARENT]->(nc3)
Cypher query for third tree - (c5)-[PARENT]->(c3)
MERGE (nc3:Category:Root{name:'c3'})
MERGE (nc5:Category {name:'c5'})-[:PARENT]->(nc3)

foreach query in cypher to merge similar nodes

I'm trying to figure out how to run through my database, collect nodes that are similar, and then merge them into a single node and re-direct the previous relationships to the newly created node.
I basically created a bunch of nodes in which some or all of the properties had info, like this:
MERGE (company:Company{Name: 'Ford'})
MERGE (person:Person{Name: 'me'})
MERGE (car:Car{Make:'Ford', Model:'Aerostar', Color:'Blue', Transmission:'Auto'})
but I accidentally duplicated nodes that should have been merged, and instead created new nodes:
MERGE (car:Car{Make:'Ford', Model:'Aerostar', Color:'', Transmission:''})
MERGE (car:Car{Make:'Ford', Model:'Aerostar', Color:'Blue', Transmission:''})
MERGE (car:Car{Make:'Ford', Model:'Aerostar', Color:'Blue', Transmission:'Auto'})
MERGE (person)-[:drives]->(car)-[:parent_company]->(company)
so, what I want do do is take the three (car) nodes I accidentally created, merge all of their properties, delete the extra relationships created by extra nodes and correct the path, so (me) would only have a single [:drives] relationship connected to a single (car) connected by a single [:parent_company] relationship.
here is what I tried, but can't quite figure out:
MATCH p=(car:Car{Make:'Ford', Model:'Aerostar'})<-[:drives]-(person:Person{Name:'me'})
FOREACH (car in nodes (p) | SET Car.Color: 'Blue', Car.Transmission:'Auto')
/////This is where I'm stuck
EDIT: Another Attempt(I get "r already declared error):
START n = node(3) //node id for complete 'aerostar' node
WITH n
MATCH (company)<-[:parent_company]-(car:Car{Make:'Ford', Model:'Aerostar')<-[r:drives]-(person)
WITH n, company, r, car, person
MERGE (person)-[r]->(n)-[:parent_company]->(company)
DELETE car
[EDITED]
Does this work for you?
MATCH (car:Car{Make:'Ford', Model:'Aerostar'})<-[d:drives]-(person:Person{Name:'me'})
DELETE d, car
WITH person
CREATE (car:Car{Make:'Ford', Model:'Aerostar', Color:'Blue', Transmission:'Auto'})<-[d:drives]-(person);
I finally figured out how to do this:
MATCH (car:Car{Make:'Ford', Model:'Aerostar'})<-[d:drives]-(person:Person{Name:'me'})
WITH car,d
SKIP 1
DELETE car,d

Resources