Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

neo4j cypher update existing node or create new node

I have a graph with approximately nine million nodes, and twelve million relationships. For each of the nodes within the graph there is a subset of properties for each respective node which forms a unique identity for the node, by Label. The graph is being updated by various data sources which augment existing nodes within the graph, or create new nodes if the nodes don't exist. I don't want to create duplicates according to the unique set of properties within the graph during the update.

For example, I have People in the graph, and their uniqueness is determined by their first name and last name. The following code is to create two distinct people:

CREATE (p:Person{first:"barry",last:"smith",height:187});
CREATE (p:Person{first:"fred",last:"jones",language:"welsh"});

Later, from one of the data sources I receive the following data records (one per line):

first: "fred", last: "lake", height: 201
first: "barry", last: "smith", language: "english"
first: "fred", last: "jones", language: "welsh", height: 188
first: "fred", last: "jones", eyes: "brown"
first: "barry", last: "smith"

After updating the graph I want to have the following nodes:

(:Person{first:"fred",last:"jones",language:"welsh",height:"188,eyes:"brown"})
(:Person{first:"barry",last:"smith",language"english",height:187})
(:Person{first:"fred",last"lake",height:201})

I'm trying to formulate a MERGE query which can do this kind of update. I have come up with the following approach:

  • Start with a MERGE that uses the uniqueness properties (first and last from the example) to find or create the initial node;
  • Then do a SET containing each property defined in the incoming record.

So, for the three examples records given above:

MERGE (p:Person{first:"fred",last:"lake"}) SET p.height = 201;
MERGE (p:Person{first:"barry",last:"smith"}) SET p.language = "english";
MERGE (p:Person{first:"fred",last:"jones"}) SET p.language = "welsh", p.height = 188;
MERGE (p:Person{first:"fred",last:"jones"}) SET p.eyes = "brown";
MERGE (p:Person{first:"barry",last:"smith"});

I've tried this out and it works, but I'm curious to know whether this is the best way (most efficient...) to ensure uniqueness in the nodes based on a set of properties, and allow additional information to be added (or not) as updates come in over time?

like image 762
s5b Avatar asked Aug 07 '14 08:08

s5b


People also ask

Can u relabel node in Neo4j?

You can change the nodes associated with a label but you can't change the type of a relationship.

Which of the following is the correct way of creating a node in Neo4j?

To create a single node in Neo4j, specify the name of the node along with CREATE statement. Syntax: CREATE (node_name);

How do you create a relationship between existing nodes in Neo4j?

To create a relationship between two nodes, we first get the two nodes. Once the nodes are loaded, we simply create a relationship between them. The created relationship is returned by the query.

Which clause is used to add new properties to an existing node or relationship?

SET clause is used to add new properties to an existing Node or Relationship.


1 Answers

Just a naive approach: what if you run a MERGE and just create or update it?

Given your list of records, consider each record as a map:

{ first: "fred", last: "lake", height: 201 }
{ first: "barry", last: "smith", language: "english" }
{ first: "fred", last: "jones", language: "welsh", height: 188 }
{ first: "fred", last: "jones", eyes: "brown" }
{ first: "barry", last: "smith" }

Then write your query in a parametric way:

MERGE (p:Person{ first: { map }.name, last: { map }.last }
ON CREATE SET n = { map }
ON MATCH  SET n += { map }

Description of the query:

  • In case of creation it should create a new node using all the properties passed in the {map}
  • In case of matching it should add new properties to the node without deleting any

I've run some queries in console of the page linked above with a MERGE ON MATCH and it seems to update existing properties to new values. The queries I've run are the following:

MATCH (peter { name: 'Peter' }) RETURN peter
MERGE (peter { name: 'Peter' }) ON MATCH SET peter += { hungry: TRUE , position: 'Entrepreneur' }
MATCH (peter { name: 'Peter' }) RETURN peter
// added two new properties here
MERGE (peter { name: 'Peter' }) ON MATCH SET peter += { hungry: FALSE , position: 'Entrepreneur' }
MATCH (peter { name: 'Peter' }) RETURN peter
// hungry is now false in here
like image 133
MarcoL Avatar answered Oct 28 '22 04:10

MarcoL