CREATE
Syntax for nodes
The CREATE
clause allows you to create one or more nodes.
Each node can be assigned labels and properties.
You can bind each node to a variable that you can refer to later in the query.
Multiple labels are separated by colons.
CREATE (charlie:Person:Actor {name: 'Charlie Sheen'}), (oliver:Person:Director {name: 'Oliver Stone'})
As of Neo4j 5.18, multiple labels can also be separated by an ampersand &
, in the same manner as it is used in label expressions.
Separation by colon :
and ampersand &
cannot be mixed in the same clause.
CREATE (charlie:Person&Actor {name: 'Charlie Sheen'}), (oliver:Person&Director {name: 'Oliver Stone'})
Both of the above queries create two nodes, bound to the variables charlie
and oliver
, each with a Person
label and a name
property.
The node representing Charlie Sheen also has the label Actor
while the node representing Oliver Stone is assigned the label Director
.
Syntax for relationships
Relationships can also be created using the CREATE
clause.
Unlike nodes, relationships always need exactly one relationship type and a direction.
Similar to nodes, relationships can be assigned properties and relationship types and be bound to variables.
CREATE (charlie:Person:Actor {name: 'Charlie Sheen'})-[:ACTED_IN {role: 'Bud Fox'}]->(wallStreet:Movie {title: 'Wall Street'})<-[:DIRECTED]-(oliver:Person:Director {name: 'Oliver Stone'})
This query creates the Person
nodes for Charlie Sheen and Oliver Stone and the Movie
node for Wall Street.
It also created the relationships of the types ACTED_IN
and DIRECTED
between them.
Reusing variables
The previous example created a path between the specified nodes. Note, that these newly created nodes and relationships are not connected to what was previously in the graph. To connect them to already existing data, bind the desired nodes and relationships to variables. These variables can then be passed along to subsequent clauses in a query that target pre-existing elements in the graph.
MATCH (charlie:Person {name: 'Charlie Sheen'}), (oliver:Person {name: 'Oliver Stone'})
CREATE (charlie)-[:ACTED_IN {role: 'Bud Fox'}]->(wallStreet:Movie {title: 'Wall Street'})<-[:DIRECTED]-(oliver)
In this example, the MATCH
clause finds the nodes Charlie Sheen and Oliver Stone and binds them to the charlie
and oliver
variables respectively.
These variables are then passed along to the subsequent CREATE
clause, which creates new relationships from the bound nodes.
You can also reuse variables from the same CREATE
, both in the same or a later clause.
This way, you can, for example, define constructs that are more complex than just a linear path.
CREATE p = (charlie:Person:Actor {name: 'Charlie Sheen'})-[:ACTED_IN {role: 'Bud Fox'}]->(wallStreet:Movie {title: 'Wall Street'})<-[:DIRECTED]-(oliver:Person:Director {name: 'Oliver Stone'}), (wallStreet)<-[:ACTED_IN {role: 'Gordon Gekko'}]-(michael:Person:Actor {name: 'Michael Douglas'})
RETURN length(p)
Creates all three nodes for Charlie Sheen, Oliver Stone and Michael Douglas and connects them all to the node representing the Wall Street movie. It then returns the length of the path from Charlie Sheen to Oliver Stone.
Note that when repeating a node’s variable, you may not add labels or properties to the repetition.
MATCH (charlie:Person {name: 'Charlie Sheen'})
CREATE (charlie:Actor)
This query will fail because the variable charlie
has already been bound to a pre-existing node, and therefore it cannot be reused to create a new node.
If you intend to add a label, use the SET
clause instead.
Reusing variables in properties
The value that can be assigned to a node’s or a relationship’s property can be defined by an expression.
MATCH (person:Person)
WHERE person.name IS NOT NULL
CREATE (anotherPerson:Person {name: person.name, age: $age})
This example created a Person
node with the same name as another person and the age from a parameter called age
.
Such an expression may not contain a reference to a variable that is defined in the same CREATE
statement.
This is to ensure that the value of a property is always clear.
CREATE (charlie {score: oliver.score + 1}), (oliver {score: charlie.score + 1})
This query tries to create nodes such that Charlie’s score is higher than Oliver’s and vice versa, which is a contradiction. The query therefore fails.
Use parameters with CREATE
Create node with a parameter for the properties
You can also create a graph entity from a map.
All the key/value pairs in the map will be set as properties on the created relationship or node.
In this case we add a Person
label to the node as well.
{
"props": {
"name": "Andy",
"position": "Developer"
}
}
CREATE (n:Person $props)
RETURN n
n |
---|
|
Rows: 1 |
Create multiple nodes with a parameter for their properties
By providing Cypher® an array of maps, it will create a node for each map.
{
"props": [ {
"name": "Andy",
"position": "Developer"
}, {
"name": "Michael",
"position": "Developer"
} ]
}
UNWIND $props AS map
CREATE (n)
SET n = map
|
Rows: 0 |
CREATE using dynamic node labels and relationship types
Node labels and relationship types can be referenced dynamically in expressions, parameters, and variables when creating nodes and relationships. This allows for more flexible queries and mitigates the risk of Cypher injection. (For more information about Cypher injection, see Neo4j Knowledge Base → Protecting against Cypher injection).
CREATE (n:$(<expr>))
CREATE ()-[r:$(<expr>)]->()
The expression must evaluate to a STRING NOT NULL | LIST<STRING NOT NULL> NOT NULL
value.
Using a LIST<STRING>
with more than one item when creating a relationship using dynamic relationship types will fail.
This is because a relationship can only have exactly one type.
{
"nodeLabels": ["Person", "Director"],
"relType": "DIRECTED",
"movies": ["Ladybird", "Little Women", "Barbie"]
}
CREATE (greta:$($nodeLabels) {name: 'Greta Gerwig'})
WITH greta
UNWIND $movies AS movieTitle
CREATE (greta)-[rel:$($relType)]->(m:Movie {title: movieTitle})
RETURN greta.name AS name, labels(greta) AS labels, type(rel) AS relType, collect(m.title) AS movies
name | labels | relType | movies |
---|---|---|---|
|
|
|
|
Rows: 1 |
INSERT
as a synonym of CREATE
INSERT
can be used as a synonym to CREATE
for creating nodes and relationships, and was introduced as part of Cypher’s GQL conformance.
However, INSERT
requires that multiple labels are separated by an ampersand &
and not by colon :
.
INSERT (tom:Person&Actor&Director {name: 'Tom Hanks'})
Creates a node, bound to the variable tom
, with the labels Person
, Actor
, and Director
and a name
property.