online learning, blog, anil singh

Mar 11

# Neo4j Basics Primer Series - Step 2

Objective: Learn graph database concepts and the first dive into Cypher.

Prerequisite: Neo4j Basics Primer Series - Step 1

A Graph database i.e. Neo4j is based on Graph Theory which talks about Graph as a set of Edges and Vertices. These Vertices and Edges are Nodes and Relationships respectively in Neo4j. The Relationships connect the Nodes and form natural paths. These relationships unlike the contrived ones in RDBMS are rich and explanatory as these can be described by set of Properties. Even nodes have properties. Therefore, Neo4j is a Property Graph Database.

The edges are adjacent if there is a common vertex between the two edges and two vertices are adjacent if there is a edge between the two vertices. Adjacency is an important aspect that gives Graph Databases an upper hand  when dealing with connected data. These natural links between nodes are the pointers or the connectors between the nodes and is known as Index Free Adjacency which aids traversals without the need for indexes. The indexes are required to speed-up the lookup for starting node/s only. Once located, the index free adjacency takes care of the rest of the traversals.

A Graph is traversable if you can draw a path between all the vertices without retracing the same path.

Even the data structure,  trees,  used to store indexes and data is a Graph, a Acyclic Graph.

Neo4j consists of the following key elements,

• Nodes : represent entities; are equivalent to rows in a table in RDBMS; are represented by circles.
• Relationships : connects two nodes; represented by (directed) lines between the nodes.
• Labels : are names which organize Nodes into various groups/ types/ roles. These are equivalent to tables in RDBMS. A node can belong to more than one label. Besides, labels are used to define constraints and create indexes.
• Properties : These are the attributes  defined on the nodes and relationships. These are equivalent to columns in RDBMS which describe the rows. Properties are key:value pairs. Relationship Types are mandatory properties of relationships and every relationship must have only one type. Properties give a rich semantic description to the relationships than is possible in RDBMS.

Note: There may be zero or more Labels for a Node. There may be zero or more properties on a Node or a Relationship.

Why use Neo4j

Neo4j is Agile, Fast, ACID compliant, Scalable, Production-ready. You need nothing more than a white-board to start modelling in Neo4j. You are defining the data model while discussing the domain. The platform is best suited for data that is highly connected.

Cypher

Cypher is Neo4j Query Language, just like the standard SQL for RDBMS. There is no standard defined for NoSQL query language yet. Each NoSQL database has it own query language. Neo4j has Cypher, Couchbase has N1QL (pronounced Nickel) and so on. It is a declarative, pattern-matching query language i.e. to say you need to tell it the pattern you want to find, the how part is taken care of by Cypher.

Nodes are represented by round brackets, (). A node identifier is (n). A labelled node identifier is (n:Student). A specific node/nodes is (n:Student {name:"Anil"}). This representation denotes a node Student with name (property) as "Anil".

Relationships are represented by dashes. A undirected relationship is --. A directed relationship is <-- or -->. A specific relationship between two nodes is -[r:STUDIES_IN]->. Here 'r' is the identifier and 'STUDIES_IN' is the relationship type.

The Sample Data

Start the database engine. Refer, Step 1 of this series, if required. Download the 20160310_SampleData.cql.tar.gz  file containing Cypher queries to create nodes and relationships. This is the sample data on which I will take you through your Cypher Learning.  On the Terminal window, change directory to the one where you downloaded the aforementioned file and

1. Unzip and untar the file,
\$ tar -zxvf 20160310_SampleData.cql.tar.gz
2. Open the Terminal window and run,
neo4j-shell -file 20160310_SampleData.cql > output.txt
Check output.txt to figure out whether everything ran well or not. Alternatively, you can run these queries in Neo4j Browser or simply copy paste onto the Neo4j shell and press enter to execute. You can opt for any of the methods that you find convenient.

Once done, in the Neo4j Browser editor run,  match (n) return n; Do you see a similar output as the one below,

Fig.1 Sample Data Visualization

Ok, time to juggle with the sample data using Cypher

1. match (n)
return n;
Retrieves all nodes in the database. 'match' searches for specified  node/s or pattern in the database. 'return' is similar to the 'select' in RDBMS which determines the projection.
2. //This is a comment
match (n)
return n;
3. match (n:Student)
return n.name, n.age;
Retrieves name and age of all students. To get properties, use the notation, <node identifier>.<node property>. Similarly you can fetch properties of relationships.
return n,g;
Retrieves all students and grades. Reverse the direction of the arrow to '<--' , what did you get?
return n.name, g.name order by g.name, n.name;
Arranges the output by grade and student name in ascending order. Use 'desc' to arrange in descending order.
return n,g;
Note the missing arrow head. This checks for the relationship in either direction. The result is same as the above query.
7. match (n:Student) --> (g:Grade {name:2})
return n,g;
Retrieves all the students in grade '2'.
where g.name=2
return n,g;
This is another way of writing the above query by using the 'where' clause instead.
where not g.name=2
return n,g;
Using 'not' in 'where' clause to filter out grade 2.
10. match (s:Subject)
return distinct s.name;
Retrieves all subjects taught in the school (grade 2 and grade 3). 'distinct' is used to remove the repeating or duplicate subject names.
11. match (s:Subject)
return distinct s.name as Subject;
Using alias 'Subject' on the returned subject names.
where g.name=2
return count(*) as NoOfStudents;
Counts the number of students in grade 2.
return g as Grade,count(*) as NoOfStudents;
Counts the number of students in each grade. Neo4j doesn't need to be told about the grouping key, it figures that out automatically.
return g as Grade, collect(n.name) as Students, count(*) as NoOfStudents;
Here all students as part of the aggregate count are collected in a array/ list against each grade. Hence, apart from the count on students, you also get the name of the students in each grade.
15. match (n:Student)
return n limit 4;
Limits the students listed to 4 out of the total 6.
16. match (n:Student)
return n skip 4 limit 10;

Skips 4 and returns 2 student nodes as there are only 6 student nodes.
return n.name as Name, type(r) as Relation, g.name as Grade
union all
return t.name as Name, type(r) as Relation, g.name as Grade;
Neo4j supports union all just like SQL in RDBMS. The query retrieves the names of class teachers and students in each grade.
18. match (n)-[r]->()
return distinct type(r) as Relationships;
Fetches all the relationships that exist in the database.
19. match (n:Student)
where n.name contains 'mit'
return n;
Fetches Student nodes whose name contains 'mit'.
20. match (n:Student)
where n.name ends with 't'
return n;
Fetches Student nodes whose name end with 't'.
21. match (n:Student)
where n.name in ['Amit','Anu', 'Jaya']
return n;
Retrieves Student nodes with names 'Amit' or 'Anu' or 'Jaya'.
22. merge (n:Student {name:'Anil', age:7, sex:'M'})
return n;
If the node does not exists, creates a new Student node.
23. match (n:Student {name:'Anil', age:7, sex:'M'}), (g:Grade {name:2})
merge (n)-[r:StudiesIn]-> (g)
return n, r, g
If the student node 'Anil' and grade node '2' exist, then create the relationship 'StudiesIn' between them if it doesn't already exist.
24. Now try deleting a student 'Amit' who studies in grade '2',
delete n;
What is your observation? Can you relate this to RDBMS world? Now try again with the below query,
detach delete n;
This time the node gets deleted along with the relationship it was holding with the grade. A simple delete would be successful only if the node is an isolated node i.e. does not have any relationships. For a connected node, use 'detach delete'.
25. This is the BIG ONE!!! Deletes all nodes and relationships.
match (n)

detach delete n;
Check the data again, did you get any?
Load the sample data again in case you wish to work on the same data set. You can create your own as well.

After working through the above queries, you will find that Neo4j is a lot simpler than it looks on the outside. For people from the RDBMS world, they would find similarities between SQL and Cypher when it comes to the various clauses and operators.

Now that you have had your first dive, in the upcoming Step 3 of this series, I will talk more on Cypher queries especially the advanced part. Till then you have enough ammo for practicing and learning Cypher. Wish you a pleasant Weekend!!