Ayadi Tahar | Introduction to CRUD Operations in Neo4j with Cypher

Introduction to CRUD Operations in Neo4j with Cypher

Publish Date: 2022-10-01


Neo4j is a very popular, widely-used No-SQL graph database. In our article today, we are going to learn how to install neo4j, and we will demonstrate on how to apply CRUD operations in Neo4j with SET, Remove, Delete and Merge (Create and MATCH) clauses using CQL language .

Download and installation

Let us first try to download and install neo4j on our machine.

1 - Download Neo4J Desktop

the first thing to do is to download the latest version of Neo4J Desktop for ubuntu platform from this official download page , but if you have a different operating system, you can pick the one corresponds to you from official download page.

you will have to complete and fill a small form information, and once you're done that, they will give ability to download and provide you a Neo4j Desktop Activation Key like the next picture shows:

neo4j desktop activation key

Locate the AppImage file of Neo4j Desktop you just downloaded. And make it executable by running the following command:


chmod +x neo4j-desktop-1.4.15-x86_64.AppImage

Now you can double-click on the downloaded file to open Neo4j Desktop.

once the app opened, on the left side panel, click on Software keys icon , click add software key and paste or enter the Neo4j Desktop Activation Key provided to you by Neo4J earlier:

add neo4j desktop activation key

click add, and you are good to go.

2 - Create your first database

under projects click create a project and give it a name:

create neo4j project

click on "add local dbms" button:

add_local_dbms

Next, enter the "Database name" and "Password" in the fields and stick with version selected by default (you can choose the latest if you want to), and click on the "Create" button:

create_local_dbms_details

after it created successfully, click on it:

create_local_dbms
Step 3: Start the database

After the database is created, click on the "Start" button. Once the database is started you shall see a window similar tot this:

start_local_dbms

click on the blue "open" button , a navigation list menu will appear, choose "Neo4j Browser":

choose Neo4j Browser

a new window will appear where you can write and execute Cypher (more on that shortly) queries:

Neo4j Browser

you can also, goes to your browser and enter http://localhost:7474/. you will see the following web interface

Neo4j Browser navigator

Connect using the default username "neo4j" with the "password" you set earlier.

Whichever option you like, stick with it through the rest of our demo.

Neo4j: Data Model

As I described earlier some basics of graph data in An Introduction to Graph Data Models , the graph data can be presented in vertices (nodes) and edges (connections) rely on them and form as sort of relationship between those nodes. Both edges and vertices data have properties of key value pairs, where the key is a property name and value is a property value. For example if we have a student name Ahmed , it’s properties would be id, name, age, gender… and the node would be like that:

nodes

a label is a way to distinguish different nodes between each other (University ,student, worker). Here, the node has a label called student. As we have known, each student belong to a University. So, an edge describes the relationship between labels:

nodes relations

to model this kind of graph data in Neo4j you have to use special query language called Cypher. For that, let’s discover about Cypher Query Language (CQL).

Cypher Query Language (CQL).

Cypher is simple, yet powerful declarative graph query language that used by developers for efficient querying, updating and administering graphs. highly complicated database queries can be easily expressed using Cypher, which enabling you to focus on your domain, instead of getting lost in database access.

Many of the Cypher keywords is inspired from different approaches, such as WHERE and ORDER BY, are inspired by SQL. Pattern matching borrows expression approaches from SPARQL. Some list semantics are borrowed from languages such as Haskell and Python.

CRUD Operations using Cypher

Lets see how to do some data manipulations on graphs which involves CREATE, SET, MERGE, DELETE, and REMOVE on nodes and relationships in a fun way.

1. CREATE

In Cypher, names are case-sensitive. Which means :PERSON, :Person and :person are three different labels, as well as n and N are two different variables.

1.1 Creating Single and Multiple Nodes with label

So, to create a node ,we can follow this syntax:


CREATE (Node_Name_1),(Node_Name_2)

in the next snippet we are creating 3 nodes:


CREATE (Student),(University),(Subject)

once the node created using neo4j browser, a confirmation message shows:

create 3 nodes

When we create a node, we could add labels to it, using this syntax :


CREATE (Node_Name:Node_label)

for example to create a node named Ahmed, and has a label Student, we use the following command:


CREATE (Ahmed:Student)

To view all the nodes we have created before, use match clause without any conditions to get all results


MATCH (n) return n

by default it show data as table or text,but you can switch to graph view (click in the graph icon just below console ) to get high overview and dynamic look. after all, we are dealing with graph data:

list nodes

we created 4 nodes, and you can see that each node in the graph has its own id, that neo4j automatically generated.

It is common for a node to have multiple labels, in order to do that in neo4j, you can follow this syntax:


CREATE (Node_Name:Node_label_1:Node_label_2:Node_label_3:…)

for example Ali is an Engineer and in the same time is a Student:


CREATE (Ali:Student:Engineer)
1.2 Creating Nodes with properties

In practice, every node has properties describe it, and these properties are of type key-value pairs. so to assign properties to nodes , we can use this syntax :



for example Omar is a Student , Male and study Information Technology as Specialty:


CREATE (Omar:Student {gender:"Male", specialty:"Information Technology"})

Let’s see in graph what we created so far. The next commands shows 6 nodes , the one with red color have 2 labels:


MATCH (n) return n
list nodes

however to select only specific nodes, you can use WHERE clause After the MATCH CLAUSE (the same order as in SQL ), following the next syntax:


MATCH (node:Node_label) WHERE node.property="some_value" RETURN node;

for example to find all the male students, run the next query where s is just a variable to keep track through the query:


MATCH (s:Student) WHERE s.gender = "Male" RETURN s
much with where clause

it is useful sometimes to take a look in the text format of data in Neo4j:

much with where clause text data
1.3 Create Relations between nodes.

the general syntax to create a relationship between nodes during nodes creation, is to specify nodes, relationship and the direction , like the following:


CREATE (node1),(node2),(node3),(node1)-[r:Relation1]-> (node2),(node2) -[r:Relation1]-> (node3)

for example Nabil is a student at MIT University, we can rely on between both nodes at nodes creation like the following:


CREATE (Nabil:Student{name: "Nabil", gender: "Male", speciality: "Software Engineering", age: 25}),
    (MIT:University{name:"MIT"}),
    (Nabil)-[r:Is_Student_at]->(MIT)
    RETURN Nabil, MIT

it is useful sometimes to take a look in the text format of data in Neo4j:

nodes relationship

but if you want to rely on between existing nodes and create a relationships between them, then you will use match query with where clause to select the nodes first, using this syntax:


MATCH (a:Node_label),(b:Node_label) WHERE a.ID = ??? AND b.ID=??? CREATE (b)-[r:R] -> (a)

to demonstrate this approach, let’s first clean up the space by deleting all nodes and relationships from the database using this command (more on DELETE command shortly) :


MATCH (n)
    DETACH DELETE n

then, lets create few nodes (students, universities, companies) :


CREATE (Asma:Student {name: "Asma", gender: "Female", speciality: "Physics", age: 22})
    CREATE (Mustafa:Student {name: "Mustafa", gender: "Male", speciality: "Computer Science", age: 24})
    CREATE (Nora:Student {name: "Nora", gender: "Female", speciality: "Law", Age: 26})
    CREATE (Rania:Student {name: "Rania", gender: "Female", speciality: "Natural Science", age: 23})
    CREATE (Ali:Student {name: "Ali", gender: "Male", speciality: "Computer Science", age: 24})
    CREATE (Samir:Student {name: "Samir", gender: "Male", speciality: "Math", age: 21})
    CREATE (MIT:University {name:"MIT"})
    CREATE (Stanford:University {name:"Stanford"})
    CREATE (Google:Company {name:"Google"})
    CREATE (Amazon:Company {name:"Amazon"})

we can create relationships between those nodes in direction student-study_at-> university:


MATCH(s:Student),(u:University) WHERE s.name = "Asma" AND u.name="MIT" CREATE  (s)-[r:Study_at]->(u) RETURN s, u;
    MATCH(s:Student),(u:University) WHERE s.name = "Mustafa" AND u.name="Stanford" CREATE  (s)-[r:Study_at]->(u) RETURN s, u;

in the same manner ,you can also create in inverse order where university<-accept-students:


MATCH(s:Student),(u:University) WHERE s.name = "Rania" AND u.name="MIT" CREATE (u)-[r:Accept]->(s) RETURN s, u;
    MATCH(s:Student),(u:University) WHERE s.name = "Samir" AND u.name="MIT" CREATE (u)-[r:Accept]->(s) RETURN s, u;
    MATCH(s:Student),(u:University) WHERE s.name = "Ali" AND u.name="Stanford" CREATE (u)-[r:Accept]->(s) RETURN s, u;

currently only Ali is working at Google Company, so let's create this relationship as well:


MATCH(s:Student),(c:Company) WHERE s.name = "Ali" AND c.name="Google" CREATE (c)-[r:Hires]->(s) RETURN s, c

you can also Create a relationship with properties as well using the following syntax:


CREATE (n)-[r:Relation {property: $value}]→(m)

for example we can add 2 more relationships with properties for students Nora and Asma:


MATCH(s:Student),(u:University) WHERE s.name = "Nora" AND u.name="Stanford" CREATE  (s)-[r:Study_at {since: 2021}]->(u) RETURN s, u
    MATCH(s:Student),(c:Company) WHERE s.name = "Asma" AND c.name="Amazon" CREATE (s)-[r:Work_at {since: 2018}]->(c) RETURN c, s

to get a view for what we created so far:


MATCH (n) return n
match nodes

the relationships is the same as nodes , they get an identity field called id, you can hover over nodes to get more info about each node, relationship and properties in matter.

2. SET

Set can be used to create properties, update or remove them as well as add labels to nodes.

to update or create a property, you can follow this syntax (n: is just convention for node) :


SET n.property1 = $value1

the same way you can also Update or create several properties.


SET
n.property1 = $value1,
n.property2 = $value2

for example if we want to update the age of Sara and add a property country ,then we have to use the following command :


MATCH (Asma:Student)
    WHERE Asma.name = "Asma"
    SET Asma.age = 23, Asma.contry = "Algeria"
    RETURN  Asma

We could also use SET Clause to set multiple labels for some nodes using criteria. Because Rania works also at Google , here we add "Employee" label to her:


MATCH (s:Student)
    WHERE s.name = "Rania"
    SET s:Employee
    RETURN  s
ad label to nodes

we can use an empty map ({}) to remove any existing properties.


SET e = {}

let’s say MIT university did not accept Samir candidate, so we want to remove all properties for related to him from the database (only the id will be left):


MATCH (s:Student)
    WHERE s.name = "Samir"
    SET s = {}
    RETURN  s
empty properties

3. Merge

merge command work as up-sert method, which means it will update the nodes and relationships with properties and labels if those already exist in the database, given a particular condition. otherwise, it will create (insert) those nodes and relationships along with the defined properties as well.

3.1 Merge command for nodes
Using Merge command with labels and properties.

In the next example, Sara node and since it does not exist in the database, Merge command will create that node ,with the properties we specified :


MERGE (Sara:Student {name:"Sara", gender:"Female"})
    RETURN  Sara

╒═════════════════════════════════╕
│"Sara"                           │
╞═════════════════════════════════╡
│{"gender":"Female","name":"Sara"}│
└─────────────────────────────────┘

We will use merge command to create the same Sara node again, but with name and age properties:


Merge(Sara:Student {name:"Sara", age:"27"})
    RETURN  Sara

╒══════════════════════════╕
│"Sara"                    │
╞══════════════════════════╡
│{"name":"Sara","age":"27"}│
└──────────────────────────┘

the merge command instead create a new node, even we have Sara in our database. that because it think it is different node as it have different properties.

now let’s find the nodes we just created and their properties:


Merge(Student {name:"Sara"})
    return Student.name, Student.gender, Student.age
    
╒══════════════╤════════════════╤═════════════╕
│"Student.name"│"Student.gender"│"Student.age"│
╞══════════════╪════════════════╪═════════════╡
│"Sara"        │"Female"        │null         │
├──────────────┼────────────────┼─────────────┤
│"Sara"        │null            │"27"         │
└──────────────┴────────────────┴─────────────┘
Merge Command With conditional updates

You can use Merge Command to match a pattern or create it if it does not exist. Use ON CREATE and ON MATCH for conditional updates. For example will add the age and subscribeTime to the nodes that have name property equal to “Sara” :


MERGE (Sara:Student {name: "Sara"})
    ON CREATE SET Sara.age = 24
    ON MATCH SET
    Sara.age = 24,
    Sara.subscribeTime = timestamp()
    RETURN Sara

╒══════════════════════════════════════════════════════════════════════╕
│"Sara"                                                                │
╞══════════════════════════════════════════════════════════════════════╡
│{"subscribeTime":1664046370438,"gender":"Female","name":"Sara","age":2│
│4}                                                                    │
├──────────────────────────────────────────────────────────────────────┤
│{"subscribeTime":1664046370438,"name":"Sara","age":24}                │
└──────────────────────────────────────────────────────────────────────┘
MERGE command with ON MATCH clause to update multiples nodes:

for example. as we know, every student is a person, so let’s traverse through all the student nodes and add a boolean property that indicate that they are Persons and differ them from company and university nodes.

We will use a merge command to find all the nodes with label Student and add a new property Is_Person to be true:


Merge (s:Student)
    ON MATCH SET s.Is_Person = TRUE
    RETURN s.name, s.Is_Person

╒═════════╤═════════════╕
│"s.name" │"s.Is_Person"│
╞═════════╪═════════════╡
│"Ali"    │true         │
├─────────┼─────────────┤
│null     │true         │
├─────────┼─────────────┤
│"Sara"   │true         │
├─────────┼─────────────┤
│"Sara"   │true         │
├─────────┼─────────────┤
│"Asma"   │true         │
├─────────┼─────────────┤
│"Mustafa"│true         │
├─────────┼─────────────┤
│"Nora"   │true         │
├─────────┼─────────────┤
│"Rania"  │true         │
└─────────┴─────────────┘
3.2 Merge command for relationships

you can also use MERGE to find or create a relationship between the nodes using this syntax:


MATCH
(a:Person {name: $value1}),
(b:Person {name: $value2})
MERGE (a)-[r:LOVES]→(b)

Suppose Asma and Rania are two friends study at MIT University. we want to create relationships between them as they are friends. We could run the following commands:


MATCH (s1:Student),(s2:Student),(u:University)
    WHERE s1.name="Asma" and s2.name="Rania" and u.name="MIT"
    MERGE (s1)-[r:Friend]->(s2)
    RETURN s1,s2,u
create relationship with merge

we have another scenario where Mustafa gets a job at Amazon, and this will make both graphs connected:


MATCH (s:Student {name:"Mustafa"}), (c:Company {name:"Amazon"})
    MERGE (s)-[r:Work_at]->(c)
    RETURN s,c
mustafa amazon work relationship

to see all the graph together:

match all nodes

4. DELETE

In our scenario example, Sara was a trainee, and Samir can’t be accepted in MIT university. So, both nodes have to be deleted.

The DELETE command can be used to delete nodes and/or relationships between those nodes.

4.1 delete one relationship of a node

the approach toward deleting nodes is to delete relationships first. so To delete a relationship, specify its id or use any condition like that:


MATCH ()-[r]->()
WHERE r.id = 123
DELETE r

for example in our graph, Samir is no longer have any properties as it was rejcted at MIT University, we can delete the relationship between them. If we look to our graph the id of relationship is 21 :

relationship id

to delete this relationship, we execute the following command:


MATCH (u)-[r:Accept]->(n)
    WHERE ID(r) = 21
    DELETE r

Deleted 1 relationship, completed after 2 ms.

If you look to graph again you will see that the node is disconnected

4.2 delete all relationships of one node

if we want to delete all relationships of a node at once (this result in disconnecting the node from the graph ):


MATCH ()-[r]->()
DELETE r

lets say for example Rania is no longer study at MIT university, and it is not a friend of asma anymore as well. to delete all relationships connected to Rania:


MATCH ()-[r]->(n)
    WHERE n.name= "Rania"
    DELETE r

Deleted 2 relationships, completed after 2 ms.
4.3 Delete a node and all relationships connected to it

We can also delete the node and the relationships connected to it as well, let say Stanford University decided to delete all information related to Nora:


MATCH (n)
    WHERE n.name= "Nora"
    DETACH DELETE n

Deleted 1 node, deleted 1 relationship, completed after 1 ms.
Delete all relationships

if we want to delete all relationships at once (this result in nodes being fully disconnected ), we select all nodes


MATCH ()-[r]->()
    DELETE r

Deleted 6 relationships, completed after 2 ms.

5. Remove

We can use remove command to remove a label from a node using this syntax : REMOVE n:ExampleLabel .

For example we set earlier that Rania is employee at Google (has labeled : employee) , now it is no longer working with them, lets remove the label:


MATCH (n:Employee)
    WHERE n.name = "Rania"
    REMOVE n:Employee

Removed 1 label, completed after 2 ms.

You can also remove a property using this syntax :REMOVE e.property

for example if we want to remove the age property of Asma student, we would do that using the following command:


MATCH (n:Student)
    WHERE n.name = "Asma"
    REMOVE n.age

Set 1 property, completed after 2 ms.
Delete all nodes and relationships

to delete all nodes and relationships from the database, you can select all nodes detach them ( delete the relationships between the nodes) then delete them using the following command:


MATCH (n)
    DETACH DELETE n

Deleted 12 nodes, completed after 2 ms.

Conclusion

Now we come to the end of our article, I hope you are now familiar of the basics of CRUD operation in Neo4j using Cypher language.

Resources:

neo4j documentation