Creating Data

The library has support for procedures that add to the write functionality that comes with Neo4j. Many of these procedures enable dynamic data creation, such as dynamically adding node labels and node or relationship properties.

CALL apoc.create.node(['Label'], {key:value,…​})

create node with dynamic labels

CALL apoc.create.nodes(['Label'], [{key:value,…​}])

create multiple nodes with dynamic labels

CALL apoc.create.addLabels( [node,id,ids,nodes], ['Label',…​])

adds the given labels to the node or nodes

CALL apoc.create.removeLabels( [node,id,ids,nodes], ['Label',…​])

removes the given labels from the node or nodes

CALL apoc.create.setProperty( [node,id,ids,nodes], key, value)

sets the given property on the node(s)

CALL apoc.create.setProperties( [node,id,ids,nodes], [keys], [values])

sets the given properties on the nodes(s)

CALL apoc.create.setRelProperty( [rel,id,ids,rels], key, value)

sets the given property on the relationship(s)

CALL apoc.create.setRelProperties( [rel,id,ids,rels], [keys], [values])

sets the given properties on the relationship(s)

CALL apoc.create.relationship(person1,'KNOWS',{key:value,…​}, person2)

create relationship with dynamic rel-type

CALL apoc.nodes.link([nodes],'REL_TYPE')

creates a linked list of nodes from first to last

CALL apoc.merge.node(['Label'], identProps:{key:value, …​}, onCreateProps:{key:value,…​}, onMatchProps:{key:value,…​}})

merge nodes with dynamic labels, with support for setting properties ON CREATE or ON MATCH

CALL apoc.merge.relationship(startNode, relType, identProps:{key:value, …​}, onCreateProps:{key:value, …​}, endNode, onMatchProps:{key:value, …​})

merge relationship with dynamic type, with support for setting properties ON CREATE or ON MATCH

CALL apoc.create.removeProperties( [node,id,ids,nodes], [keys])

removes the given properties from the nodes(s)

CALL apoc.create.removeRelProperties( [rel,id,ids,rels], [keys])

removes the given properties from the relationship(s)

Remove Node Labels

Cypher supports deleting of labels as long as the labels are hard coded. If the labels are dynamically specified, we can use the apoc.create.removeLabels procedure.

The following creates a sample graph of people:
CREATE (jennifer:Person:US {name: "Jennifer", community: 1, partition: 4})
CREATE (karin:Person:US {name: "Karin", community: 4, partition: 2})
CREATE (mark:Person:UK {name: "Mark", community: 3, partition: 3})
The following removes all labels except Person from all nodes:
CALL db.labels()
YIELD label WHERE label <> "Person"
WITH collect(label) AS labels
MATCH (p:Person)
WITH collect(p) AS people, labels
CALL apoc.create.removeLabels(people, labels)
YIELD node
RETURN node, labels(node) AS labels
Table 1. Results
node labels

(:Person {name: "Jennifer", partition: 4, community: 1})

["Person"]

(:Person {name: "Karin", partition: 2, community: 4})

["Person"]

(:Person {name: "Mark", partition: 3, community: 3})

["Person"]

Set Node and Relationship Properties

Cypher supports setting of properties as long as the property names are hard coded. If the property names are dynamically specified we can use the apoc.create.setProperties and apoc.create.setRelProperties procedures.

The following creates a sample graph of people:
CREATE (jennifer:Person {name: "Jennifer", community: 1, partition: 4})
CREATE (karin:Person {name: "Karin", community: 4, partition: 2})
CREATE (elaine:Person {name: "Elaine", community: 3, partition: 3})
MERGE (jennifer)-[:FRIENDS {since: datetime("2019-06-01")}]-(karin)
MERGE (jennifer)-[:FRIENDS {since: datetime("2019-05-04")}]-(elaine)
The following duplicates all node properties on Person nodes:
MATCH (p:Person)
WITH p, keys(p) AS keys
CALL apoc.create.setProperties(p,[k in keys | k + "Copy"], [k in keys | p[k]])
YIELD node
RETURN node
Table 2. Results
node

{"name":"Jennifer","partition":4,"community":1,"nameCopy":"Jennifer","partitionCopy":4,"communityCopy":1}

{"name":"Karin","partition":2,"community":4,"nameCopy":"Karin","partitionCopy":2,"communityCopy":4}

{"name":"Mark","partition":3,"community":3,"nameCopy":"Mark","partitionCopy":3,"communityCopy":3}

The following duplicates all relationship properties:
MATCH (:Person)-[friends:FRIENDS]->(:Person)
WITH friends, keys(friends) AS keys
CALL apoc.create.setRelProperties(friends,[k in keys | k + "Copy"], [k in keys | friends[k]])
YIELD rel
RETURN startNode(rel) AS start, rel, endNode(rel) AS end
Table 3. Results
start rel end

{ "name": "Jennifer", "partition": 4, "community": 1, "nameCopy": "Jennifer", "partitionCopy": 4, "communityCopy": 1 }

{ "sinceCopy": "2019-05-04T00:00:00Z", "since": "2019-05-04T00:00:00Z" }

{ "name": "Elaine", "partition": 3, "community": 3, "nameCopy": "Elaine", "partitionCopy": 3, "communityCopy": 3 }

{ "name": "Jennifer", "partition": 4, "community": 1, "nameCopy": "Jennifer", "partitionCopy": 4, "communityCopy": 1 }

{ "sinceCopy": "2019-06-01T00:00:00Z", "since": "2019-06-01T00:00:00Z" }

{ "name": "Karin", "partition": 2, "community": 4, "nameCopy": "Karin", "partitionCopy": 2, "communityCopy": 4 }

Remove Node and Relationship Properties

Cypher supports deleting of properties as long as the property names are hard coded. If the property names are dynamically specified we can use the apoc.create.removeProperties and apoc.create.removeRelProperties procedures.

The following creates a sample graph of people:
CREATE (jennifer:Person {name: "Jennifer", community: 1, partition: 4})
CREATE (karin:Person {name: "Karin", community: 4, partition: 2})
CREATE (elaine:Person {name: "Elaine", community: 3, partition: 3})
MERGE (jennifer)-[:FRIENDS {since: datetime("2019-06-01")}]-(karin)
MERGE (jennifer)-[:FRIENDS {since: datetime("2019-05-04")}]-(elaine)
The following deletes all properties except for name from Person nodes:
CALL db.propertyKeys()
YIELD propertyKey WHERE propertyKey <> "name"
WITH collect(propertyKey) AS propertyKeys
MATCH (p:Person)
WITH collect(p) AS nodes, propertyKeys
CALL apoc.create.removeProperties(nodes, propertyKeys)
YIELD node
RETURN node
Table 4. Results
node

{"name":"Jennifer"}

{"name":"Karin"}

{"name":"Elaine"}

The following deletes properties from all relationships:
CALL db.propertyKeys()
YIELD propertyKey
WITH collect(propertyKey) AS propertyKeys
MATCH (:Person)-[friends:FRIENDS]->(:Person)
WITH collect(friends) AS friendsRels, propertyKeys
CALL apoc.create.removeRelProperties(friendsRels, propertyKeys)
YIELD rel
RETURN startNode(rel) AS start, rel, endNode(rel) AS end
Table 5. Results
start rel end

{"name":"Jennifer"}

{}

{"name":"Elaine"}

{"name":"Jennifer"}

{}

{"name":"Karin"}

Linked Lists

Creating a linked list from a collection of nodes can be done in Cypher, but is much easier with the apoc.nodes.link procedure.

The following creates a sample graph of events:
CREATE (:Event {name: "Event 1", date: datetime("2019-06-01")})
CREATE (:Event {name: "Event 2", date: datetime("2019-06-04")})
CREATE (:Event {name: "Event 3", date: datetime("2019-06-08")})
The following creates a linked list of these events:
MATCH (e:Event)
WITH e ORDER BY e.date
WITH collect(e) AS events
CALL apoc.nodes.link(events, "NEXT")
RETURN count(*)
linked list events