## 8.1. Creating Data

This section describes functions that can be used to create data entities.

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)

This section includes:

- Section 8.1.1, “Remove Node Labels”
- Section 8.1.2, “Set Node and Relationship Properties”
- Section 8.1.3, “Remove Node and Relationship Properties”
- Section 8.1.4, “Linked Lists”

### 8.1.1. 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 8.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"]

### 8.1.2. 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 8.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 8.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 }

### 8.1.3. 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 8.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 8.5. Results
start | rel | end
--- | --- | ---
{"name":"Jennifer"} | {} | {"name":"Elaine"}
{"name":"Jennifer"} | {} | {"name":"Karin"}

### 8.1.4. 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(*)