Neo4J set new property on Relationship by Relationship ID - neo4j

I have a Neo4J Graph and want to add a new Property on the Relationships based on the ID of the Relationship, which is already set. The ID is a Property and looks like this:
id:16_0beta1_1b500480_1221807483755_439038_8369
In a CSV-File I have stored 400 IDs and a type corresponding to the IDs. Neo4J should load the CSV-File and look through all relationships. When a Relationship ID matches an ID from the CSV-File it should set the new Property like this: set r.SysML=row.type and create a new Property on the Relationship:
SysML:Block
For the nodes the following clause worked well:
LOAD CSV WITH HEADERS FROM "file:///SysML.csv" AS row
merge(n:name {id:row.sysID})
on match set n.SysML=row.type
For Relationship Property i tried:
LOAD CSV WITH HEADERS FROM "file:///SysML.csv" AS row
merge ()-[r:rel {id:row.sysID}]->()
on match set r.SysML=row.type
I couldn't solve it even with many variations of the relationship...

You should NEVER do this:
merge ()-[r:rel {id:row.sysID}]->()
If the relationship does not already exist, that clause would create a new relationship between 2 brand new nodes having no labels or properties (and your on match clause would also not be applied).
Since your question indicates you just want to update the SysML property of existing rel relationships, you should use MATCH instead of MERGE:
LOAD CSV WITH HEADERS FROM "file:///SysML.csv" AS row
MATCH ()-[r:rel {id: row.sysID}]->()
SET r.SysML = row.type
By the way, it would be more efficient if you qualified the end nodes (e.g., by supplying labels, or even property values) to avoid having to scan through every relationship in the DB.

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

neo4j relationships between PK and FK

i have two csv files the first one is like
movies.csv
movieId | title | genres
links.csv
movieId | tmdbId | imdbId
ive tried this cypher query
USING PERIODIC COMMIT 500
LOAD CSV WITH HEADERS FROM "file:///links.csv" AS row
WITH row
MATCH (movie:Movie {id: toInt(row.movieId)})
MERGE (link)-[r:LINK]->(movie)
ON CREATE SET r.tmdbId = toInt(row.tmdbId)
this didnt work for me, it doesnt create new label "LINK" or form the relationship correctly,,
i want to be able when i have a movieId to get its corresponding tmdbId
t've tried several methods but none of them worked, im new to neo4k and still familiarised with sql
Your usage of link is as a variable, not a label (you would use :Link if you wanted to create a new node with that label), and it's not really clear what your link is supposed to be, as you don't have any ids or any properties on it. It's also not clear what you need other nodes for, as a movie node can easily have properties for related ids (so you look up the :Movie node by its movieId and then get the tmdbId from that node).
If you could provide more details about your use cases, and what you want to model and how it's connected, that would help.
EDIT
Okay, so it sounds like you're modeling :Movies, and you also want :Link nodes that hold both tmdbId and imdbId properties. As mentioned above, in reality you should just set the properties on the :Movie node itself and not bother with :Link nodes at all, but this is for the sake of getting used to neo4j, so okay.
First of all, to make sure our matches are fast as we build these relationships, we need unique constraints on nodes through their unique IDs.
CREATE CONSTRAINT ON (m:Movie)
ASSERT m.id IS UNIQUE
CREATE CONSTRAINT ON (l:Link)
ASSERT l.tmdbId IS UNIQUE
CREATE CONSTRAINT ON (l:Link)
ASSERT l.imdbId IS UNIQUE
Your import would be:
USING PERIODIC COMMIT 500
LOAD CSV WITH HEADERS FROM "file:///links.csv" AS row
WITH row
MATCH (movie:Movie {id: toInt(row.movieId)})
MERGE (link:Link{imdbId: toInt(row.imdbId), tmdbId: toInt(row.tmdbId)})
MERGE (link)-[:LINK]->(movie)
And a query to get the movie by one id would be:
MATCH (link:Link)-[:LINK]->(movie:Movie)
WHERE link.imdbId = 123
RETURN movie
You should be able to infer the query for going the opposite direction, starting with a movieId and traversing the :LINK relationship to the :Link node (you may want to change one of these, as having the same name for a node label and a relationship type might get confusing since you're new to this) to get the relevant ID.

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;

How to create a relationship to existing nodes based on a condition of matching properties

In Neo4j, I am trying to load a CSV file whilst creating a relationship between nodes based on the condition that a certain property is matched.
My Cypher code is:
LOAD CSV WITH HEADERS FROM "file:C:/Users/George.Kyle/Simple/Simple scream v3.csv" AS
csvLine
MATCH (g:simplepages { page: csvLine.page}),(y:simplepages {pagekeyword: csvLine.keyword} )
MATCH (n:sensitiveskin)
WHERE g.keyword = n.keyword
CREATE (f)-[:_]->(n)
You can see I am trying to create a relationship between 'simplepages' and 'sensitiveskin' based on their keyword properties being the same.
The query is executing but relationships won't form.
What I hope for is that when I execute a query such as
MATCH (n:sensitiveskin) RETURN n LIMIT 25
You will see all nodes (both sensitive skin and simple pages) with auto-complete switched on.
CREATE (f)-[:_]->(n) is using an f variable that was not previously defined, so it is creating a new node (with no label or properties) instead, and then creating a relationship from that new node. I think you meant to use either g or y instead of f. (Probably y, since you don't otherwise use it?)

How to generate relationships using property information [Node4j]

I have imported a CSV where each Node contains 3 columns. id, parent_id, and title. This is a simple tree structure i had in mysql. Now i need to create the relationships between those nodes considering the parent_id data. So each node to node will have 2 relationships as parent and child. Im really new to node4j and suggestions ?
i tried following, but no luck
MATCH (b:Branch {id}), (bb:Branch {parent_id})
CREATE (b)-[:PARENT]->(bb)
It seems as though your cypher is very close. The first thing you are going to want to do is create an index on the id and parent_id properties for the label Branch.
CREATE INDEX ON :Branch(id)
CREATE INDEX ON :Branch(parent_id)
Once you have indexes created you want to match all of the nodes with the label Branch (I would limit this with a specific value to start to make sure you create exactly what you want) and for each find the corresponding parent by matching on your indexed attributes.
MATCH (b:Branch), (bb:Branch)
WHERE b.id = ???
AND b.parent_id = bb.id
CREATE (b)-[:PARENT]->(bb)
Once you have proved this out on one branch and you get the results you expect I would run it for more branches at once. You could still choose to do it in batches depending on the number of branches in your graph.
After you have created all of the :PARENT relationships you could optionally remove all of the parent_id properties.
MATCH (b:Branch)-[:PARENT]->(:Branch)
WHERE exists(b.parent_id)
REMOVE b.parent_id

Resources