CREATE UNIQUE in Neo4j not working? - neo4j

I currently have a graph database that tries to model geographical data.
For the sake of simplicity, one of the relationships I'm using is (Object)-[:IS_IN]-(Object) to relate entities (for example place1 is in city1).
Right now I'm trying to add certain places to the DB, while trying to preserve any kind of already existing nodes. So if for example I already have a relationship such as (place1)-[:is_in]->(city1) and then try to add a (place2)-[is_in]->(city1) relationship, it should link place 2 back to the existing city1 node instead of creating a new one with the same name. So I tried using CREATE UNIQUE like this:
MATCH (obj:Object {name: 'place2'}) CREATE UNIQUE (obj)-[:IS_IN]->(city:Object {name: 'city1' })
However, this keeps creating new nodes named city1. What gives? Should I be using MERGE instead?

Use
MATCH (obj:Object {name: 'place2'}), (city:Object {name: 'city1' } CREATE UNIQUE (obj)-[:IS_IN]->(city)
instead.

I came across the same problem and found this solution that works fine for me :
MERGE (obj:Object {name: 'place2'}) MERGE (city:Object {name: 'city1' }) CREATE UNIQUE (obj)-[:IS_IN]->(city)
What this does (as I understand it) : Finds 'place2' node or creates it if it doesn't exist, finds 'city1' node or creates it if it doesn't exist, creates a :IS_IN relationship if it doesn't exist.
So, whatever the initial situation is, you end up with the complete pattern, but no node or relationship dupl.
I tested it with various starting situations and it worked as expected.
Note that I'm a Neo4j and cypher beginner, this may not be the best solution.
The question is old, I answered it anyway because other people may find it useful.

Related

Neo4J - Creating Relationship on existing nodes

I am new to Neo4J and I am looking to create a new relationship between an existing node and a new node.
I have a university node, and person node.
I am trying to assign a new person to an existing university.
I am trying to following code:
MATCH (p:Person {name:'Nick'}), (u:University {title:'Exeter'}) CREATE (p)-[:LIKES]->(u)
So in the above code: MATCH (p:Person {name:'Nick'}) is the new user
AND (u:University {title:'Exeter'}) is the exisiting univeristy.
But it is coming back (no changes, no rows)
I have even tried the query without the MATCH part but no luck either.
I have looked at few similar answers but they didn't seem to work either.
Any help would be very much appreciated. Thank you.
Match before u create new one, as suggested in the comments!
MATCH(u:University {title:'Exeter'})
CREATE(p:Person {name:'Nick'})
CREATE(p)-[w:LIKES]->(u)
return w
You could also use a MERGE statement as per the docs:
MERGE either matches existing nodes and binds them, or it creates new data and binds that. It’s like a combination of MATCH and CREATE that additionally allows you to specify what happens if the data was matched or created.
You would do a query like
MERGE (p:Person {name:'Nick'})-[:LIKES]->(u:University {title:'Exeter'})
It is because when you match you search for a nodes in your db. The db says i can't make the realtion "when the nodes dont exist".
Luckily there is something called merge it is like a match +create when he does not find the whole path he creates it.
it should be something like merge 'node1' merge'node2' create(node1)[]->(node2)

neo4j relationships between nodes using a common property (id) without creating more nodes

I have been trying to match together two different nodes (process) and (process framework) that have the same id. I want to set a relationship between those (called:SAME).
The query works but it creates 3 times the amount of processes that I wanted and I can´t figure out why:
MATCH (p:Process)
MATCH (pcf:ProcessFramework)
WHERE HAS (p.id) AND HAS (pcf.pcf_id) AND p.id=pcf.pcf_id
MERGE (p)<-[:same]-(pf)
return p,pcf
I also tried it with CREATE UNIQUE instead of MERGE but its the same result. I am not a developer so maybe I am doing a very obvious mistake but I really can´t see it!
Thanks!
You have a typo in your query, you use pf where you should use pcf in the MERGE.
I'd also change it to this and make sure you have an index on :ProcessFramework(pcf_id)
MATCH (p:Process)
MATCH (pcf:ProcessFramework)
WHERE p.id=pcf.pcf_id
MERGE (p)<-[:same]-(pcf)
return p,pcf

Cypher: Create relationships between nodes based on a common property key id

I'm brand new to Cypher (and Stackoverflow) and am having trouble creating relationships between nodes based on share property keys.
I would like to do something like this:
MATCH (a:Person)-->()<--(b:Country)
WHERE HAS (a.id) AND HAS (b.id) AND a.id=b.id
CREATE (a)-[:LIVES]->(b);
to create a relationship between Country node and Person nodes where they share the same id.
The above creates no errors when run but doesn't create any relationships either and I know that the ids should match.
Many thanks!!
EDIT:
I think I know what is going wrong - I'm asking to match nodes that have a relationship to eachother but no relationships are set up yet hence 0 results. I have now tried:
MATCH (a:Person),
(b:Country)
WHERE HAS (a.id) AND HAS (b.id) AND a.id=b.id
CREATE (a)-[:LIVES]->(b);
and the query is running. It's a big data set so might take a while......
That worked. Had to reduce the size of my data set (down from 64k nodes) as Neo4j was taking way too long to process but once I had a smaller set it worked fine.
One minor addition for future Googlers.
per the help files as of version 3.4
The has() function has been superseded by exists() and has been removed.
The new code should read
MATCH (a:Person),
(b:Country)
WHERE EXISTS (a.id) AND EXISTS (b.id) AND a.id=b.id
CREATE (a)-[:LIVES]->(b);

how to create unique relationships neo4j 2.0

I am trying to create some unique relationships between entities in neo4j. Right now I have authors and articles, with a Authored relationship between them. I want to create a CoAuthored relationship between the entities
Like so
match (a)-[r]->(b)<-[r2]-(c)
create (a)-[new:CoAuthor]->(c)
However, I would like to create a unique co-author relationship, but update the weight if it already exists. I saw this postm but the syntax is no longer supported In Cypher, how can I create a relationship if it doesn't exist; update property if it does
SyntaxException: This syntax is no longer supported (missing properties are now returned as null). Please use (not(has(<ident>.weight)) OR <ident>.weight=<value>) if you really need the old behavior.
I do not quite understand what it is that I am replacing. I looked at the Merge command, but can't quite get it to work
You should be able to replace create with merge in this particular case.
match (a)-[r]->(b)<-[r2]-(c)
merge (a)-[new:CoAuthor]->(c)
on create set new.weight=1
on match set new.weight=new.weight+1

Creating relationship conditionally with cypher (neo4j)

I am attempting to create a linked list with neo4j, and have a root node with no relationships. Here is the pseudo cypher I am trying to create, but I am not sure how, or even if it is possible:
START root=node(1), item=node(2)
MATCH root-[old?:LINK]->last
WHERE old IS NOT NULL
CREATE root-[:LINK]->item-[:LINK]->last
DELETE old
WHERE old IS NULL
CREATE root-[:LINK]->item
Basically I am trying to insert a node into the list if the list exists, and simply create the first list item otherwise. Obviously you cannot do multiple WHEREs like I have done above. Any ideas how I can achieve this desired functionality with a cypher?
The docs solve the problem by first creating a recurrent :LINK relationship on the root node, but I would like to solve this without doing that (as you then need to create possibly unnecessary relationships for each node).
For anyone interested, I figured out a way to solve the above using some WITH tricks. This is essentially a solution for creating linked lists in neo4j without having to first create a self referencing relationship.
START root=node(1), item=node(2)
MATCH root-[old?:LIST_NEXT]->last
CREATE root-[:LIST_NEXT]->item
WITH item, old, last
WHERE old IS NOT NULL
CREATE item-[:LIST_NEXT]->last
DELETE old
This works by first looking for an existing link relationship, and creating the new one from the root to the item. Then by using WITH we can chain the query to now examine whether or not the matched relationship did in fact exist. If it did, then remove it, and create the remaining link piece from the new item to the old one.
For this, you might want to look at MERGE, http://docs.neo4j.org/chunked/snapshot/query-merge.html#merge-merge-with-on-create-and-on-match
And maybe at the linked list example, http://docs.neo4j.org/chunked/snapshot/cookbook-linked-list.html

Resources