how to create unique relationships neo4j 2.0 - neo4j

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

Related

How could i use this SQL on cypher(neo4j)

hi how can i transform this SQL Query as CYPHER Query ? :
SELECT n.enginetype, n.Rocket20, n.Yearlong, n.DistanceOn,
FROM TIMETAB AS n
JOIN PLANEAIR AS p ON (n.tailnum = p.tailNum)
If it is requisition before using that query to create any relationship or antyhing please write and help with that one too.. thanks
Here's a good guide for comparing SQL with Cypher and showing the equivalent Cypher for some SQL queries.
If we were to translate this directly, we'd use :PLANEAIR and :TIMETAB node labels (though I'd recommend using better names for these), and we'll need a relationship between them. Let's call it :RELATION.
Joins in SQL tend to be replaced with relationships between nodes, so we'll need to create these patterns in your graph:
(:PLANEAIR)-[:RELATION]->(:TIMETAB)
There are several ways to get your data into the graph, usually through LOAD CSV. The general approach is to MERGE your :PLANEAIR and :TIMETAB nodes with some id or unique property (maybe TailNum?, use ON CREATE SET ... after the MERGE to add the rest of the properties to the node when it's created, and then MERGE the relationship between the nodes.
The MERGE section of the developers manual should be helpful here, though I'd recommend reading through the entire dev manual anyway.
With this in place, the Cypher equivalent query is:
MATCH (p:PLANEAIR)-[:RELATION]->(n:TIMETAB)
RETURN n.Rocket20,p.enginetype, n.year, n.distance
Now this is just a literal translation of your SQL query. You may want to reconsider your model, however, as I'm not sure how much value there is in keeping time-related data for a plane separate from its node. You may just want to have all of the :TIMETAB properties on the :PLANEAIR node and do away with the :TIMETAB nodes completely. Of course your queries and use cases should guide how to model that data best.
EDIT
As far as creating the relationship between :PLANEAIR and :TIMETAB nodes (and again, I recommend using better labels for these, and maybe even keeping all time-related properties on a :Plane node instead of a separate one), provided you already have those nodes created, you'll need to do a joining match, but it will help to have a unique constraints on :PLANEAIR(tailnum) :TIMETAB(tailNum) (or an index, if this isn't supposed to be a unique property):
CREATE CONSTRAINT ON (p:PLANEAIR)
ASSERT p.tailNum IS UNIQUE
CREATE CONSTRAINT ON (n:TIMETAB)
ASSERT n.TailNum IS UNIQUE
Now we're ready to create the relationships
MATCH (p:PLANEAIR)
MATCH (n:TIMETAB)
WHERE p.tailNum = n.tailNum
CREATE (p)-[:RELATION]->(n)
REMOVE n.tailNum
Now that the relationships are created, and :TIMETAB tailNum property removed, we can drop the unique constraint on :TIMETAB(tailNum), since the relationship to :PLANEAIR is all we need.
DROP CONSTRAINT ON (n:TIMETAB)
ASSERT n.tailNum IS UNIQUE

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);

CREATE UNIQUE in Neo4j not working?

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.

Resources