0% found this document useful (0 votes)
21 views35 pages

Graph NoSQL Databases with Neo4j

The document covers the use of Graph NoSQL databases, specifically focusing on Neo4j, which allows for the storage of entities (nodes) and their relationships (edges). It explains the features, query capabilities using Cypher, and the creation of nodes, relationships, indexes, and constraints within the Neo4j environment. The document also highlights the advantages of graph databases over traditional relational databases in terms of data organization and query efficiency.

Uploaded by

sit22it104
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
21 views35 pages

Graph NoSQL Databases with Neo4j

The document covers the use of Graph NoSQL databases, specifically focusing on Neo4j, which allows for the storage of entities (nodes) and their relationships (edges). It explains the features, query capabilities using Cypher, and the creation of nodes, relationships, indexes, and constraints within the Neo4j environment. The document also highlights the advantages of graph databases over traditional relational databases in terms of data organization and query efficiency.

Uploaded by

sit22it104
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

PROFESSIONAL ELECTIVES - I

20ITEL609 L T P C
SDG NO. 4, 9, 11 NoSQL DATABASE TECHNIQUES
3 0 0 3
& 12

UNIT V GRAPH NOSQL DATABASES


Graph NoSQL databases using Neo4-NoSQL database development tools and
programming languages- Graph Databases- What Is a Graph Database?-Features-
Consistency- Transactions- Availability- Query Features- Scaling- Suitable Use Cases-
Connected Data- Routing- Dispatch and Location-Based Services- Recommendation
Engines.

Graph Databases (Neo4j)


• Graph databases allow you to store entities and relationships between these
entities.
• Entities are also known as nodes, which have properties. Think of a node as
an instance of an object in the application.
• Relations are known as edges that can have properties. Edges have
directional significance; nodes are organized by relationships which allow you
to find interesting patterns between the nodes.
• The organization of the graph lets the data to be stored once and then
interpreted in different ways based on relationships.

What Is a Graph Database?


• In the example graph in Figure, we see a bunch of nodes related to each other.
• Nodes are entities that have properties, such as name.
• The node of Martin is actually a node that has property of name set to Martin.

1
Figure: An example graph structure

• We also see that edges have types, such as likes, author, and so on.
• These properties let us organize the nodes; for example, the nodes Martin and
Pramod have an edge connecting them with a relationship type of friend.
• Edges can have multiple properties. We can assign a property of since on the
friend relationship type between Martin and Pramod.
• Relationship types have directional significance; the friend relationship type
is bidirectional but likes is not.
• When Dawn likes NoSQL Distilled, it does not automatically mean NoSQL
Distilled likes Dawn.
• Once we have a graph of these nodes and edges created, we can query the
graph in many ways, such as “get all nodes employed by Big Co that like
NoSQL Distilled.”
• A query on the graph is also known as traversing the graph. An advantage of
the graph databases is that we can change the traversing requirements without
having to change the nodes or edges.
• If we want to “get all nodes that like NoSQL Distilled,” we can do so without
having to change the existing data or the model of the database, because we
can traverse the graph any way we like.
• Usually, when we store a graph-like structure in RDBMS, it’s for a single
type of relationship (“who is my manager” is a common example).
• Adding another relationship to the mix usually means a lot of schema
changes and data movement, which is not the case when we are using
graph databases.
2
• Similarly, in relational databases we model the graph beforehand based
on the Traversal we want; if the Traversal changes, the data will have to
change.
• In graph databases, traversing the joins or relationships is very fast.
• The relationship between nodes is not calculated at query time but is actually
persisted as a relationship.
• Traversing persisted relationships is faster than calculating them for every
query.
• Nodes can have different types of relationships between them.
• Since there is no limit to the number and kind of relationships a node can
have, all they can be represented in the same graph database.

Neo4j Query Features


• Neo4j Commands to start and stop Neo4j service
$ sudo systemctl start neo4j
$ sudo systemctl stop neo4j
• On browser give following URL to connect with Neo4j database
[Link]

The Neo4j browser is a graphical user interface (GUI) that can be run through
a web browser. The Neo4j browser can be used for adding data,
running queries, creating relationships, and more. It also provides an easy
way to visualize the data in the database.
• The relationship between nodes is not calculated at query time but is actually
persisted as a relationship.
• Traversing persisted relationships is faster than calculating them for every
query.
• Nodes can have different types of relationships between them.
• Since there is no limit to the number and kind of relationships a node can
have, all they can be represented in the same graph database.

3
Overview of the Neo4j browser interface

Editor:
This is where you enter queries and commands. For example, to create or
retrieve data. You can get help at any time by entering :help and pressing enter
(or clicking the "Run" arrow to the right of the Editor).

Stream:
This is where the results of your queries appear. Each result has its own
frame. Each frame appears above the previous. So this enables you to scroll
down and view the results of a previous query if needed. You can clear the
Stream at any time by using the command :clear.

Labels, Nodes, & Relationships


These represent the data in the database. Clicking on any of the icons at
the top result in information about that option being displayed at the
bottom of the Frame.

4
Sidebar
The Sidebar has various options, such as viewing the details of your
database, viewing/changing Neo4j Browser Settings, viewing Neo4j
Documentation, and more. Clicking on an option results in a wider
sidebar sliding open, with details about that option.
For example, clicking the "Database" icon opens details about the
database.

Frame Viewing Options


This enables you to view the data in different ways. Clicking on Rows for
example, will display the nodes and relationships in rows.

5
Neo4j Query Language - Cypher
• Neo4j has its own query language called Cypher. Cypher uses a similar syntax
to SQL (Structured Query Language).
Example
MATCH (p:Person { name:"Homer Flinstone" })
RETURN p

This Cypher statement returns a "Person" node where the name property is
"Homer Flinstone".
If this was SQL querying a relational database, it might look more like this:
SELECT * FROM Person
WHERE name = "Homer Flinstone";

• However, remember, Neo4j doesn't store its data in tables like the relational
database model. It's all in nodes and relationships. So the Cypher query above
is querying nodes, their labels, and their properties. The SQL example on the
other hand, is querying tables, rows, and columns.
• SQL was designed to be used with relational database management systems
(DBMS). Neo4j is a NoSQL DBMS, in that it doesn't use the relational model
and it doesn't use SQL.

6
• Cypher was designed specifically for working with the Neo4j data model,
which is all about nodes and their relationships with each other.

ASCII-Art Syntax
• Cypher uses ASCII-Art to represent patterns. This is a handy thing to
remember when first learning the language. If you forget how to write
something, just visualise how the graph will look and it should help.
(a)-[:KNOWS]->(b)

The main things to remember:


• Nodes are represented by parentheses, which look like circles. Like this: (node)
• Relationships are represented by arrows. Like this: ->
• Information about a relationship can be inserted between square brackets.
Like this: [:KNOWS]

Defining the Data

Here are some more points to remember when working with Cypher:
• Nodes usually have labels. Examples could include "Person", "User",
"Actor", "Employee", "Customer".
• Nodes usually have properties. Properties provide extra information about
the node. Examples could include "Name", "Age", "Born", etc
• Relationships can also have properties.
• Relationships usually have a type (this is basically like a node's label).
Examples could include "KNOWS", "LIKES", "WORKS_FOR",
"PURCHASED", etc.

So looking at the above example again:


MATCH (p:Person { name:"Homer Flinstone" })
RETURN p

We can see that:


• The node is surrounded by parentheses ().
• Person is the node's label.
• name is a property of the node.

Create a Node using Cypher


• To create nodes and relationships using Cypher, use the CREATE
statement.
• The statement consists of CREATE, followed by the details of the node or
relationship that you're creating.
Example

7
• Let's create a music database that contains band names and their albums.
• The first band will be called Strapping Young Lad. So we will create an Artist
node and call it Strapping Young Lad.
• Our first node will look something like this. Note that the name is cut short
only because it's too long to be displayed on the node. The full name is still
stored in the database.

Here's the Cypher CREATE statement to create the above node:


CREATE (a:Artist { Name : "Strapping Young Lad" })
• This Cypher statement creates a node with an Artist label. The node has a
property called Name, and the value of that property is Strapping Young Lad.
• The a prefix is a variable name that we provide. We could've called this
anything. This variable can be useful if we need to refer to it later in the
statement (which we don't in this particular case). Note that a variable is
restricted to a single statement.
• So go ahead and run the above statement in the Neo4j browser. The statement
will create the node.

Once Neo4j has created the node, you should see a message like this:

Displaying the Node


• The CREATE statement creates the node but it doesn't display the node.
• To display the node, you need to follow it up with a RETURN statement.
• Let's create another node. This time it will be the name of an album. But this
time we'll follow it up with a RETURN statement.

CREATE (b:Album { Name : "Heavy as a Really Heavy Thing", Released :


"1995" })
RETURN b

8
• The above statement creates a node with an Album label. It has two
properties: Name and Released.
• Note that we return the node by using its variable name (in this case b).

Creating Multiple Nodes


• You can create multiple nodes at once by separating each node with a comma:

• CREATE (a:Album { Name: "Killers"}), (b:Album {


Name: "Fear of the Dark"})
RETURN a,b

• Or you can use multiple CREATE statements:


CREATE (a:Album { Name: "Piece of Mind"})
CREATE (b:Album { Name: "Somewhere in Time"})
RETURN a,b

Create a Relationship using Cypher


• Just like creating nodes in Neo4j, we can use the CREATE statement to create
relationships between those nodes.
• The statement for creating a relationship consists of CREATE, followed by the
details of the relationship that you're creating.
Example
• Let's create a relationship between some of the nodes that we created previously.
First, let's create a relationship between an artist and an album.
• We'll create the following relationship:

Here's the Cypher CREATE statement to create the above relationship:


MATCH (a:Artist),(b:Album)
WHERE [Link] = "Strapping Young Lad" AND
[Link] = "Heavy as a Really Heavy Thing"

CREATE (a)-[r:RELEASED]->(b)
RETURN r

Explanation of the Above Code


• First, we use a MATCH statement to find the two nodes that we want to
create the relationship between.
• There could be many nodes with an Artist or Album label so we narrow it
down to just those nodes we're interested in. In this case, we use a property value
9
to filter it down. We use the Name property that we'd previously assigned to
each node.
• Then there's the actual CREATE statement. This is what creates the
relationship. In this case, it references the two nodes by the variable name (i.e. a
and b) that we gave them in the first line.

The relationship is established by using an ASCII-code pattern, with an arrow


indicating the direction of the relationship: (a)-[r:RELEASED]->(b).
• We give the relationship a variable name of r and give the relationship a type
of RELEASED (as in "this band released this album"). The relationship's type is
analogous to a node's label.

Adding More Relationships


• The above example is a very simple example of a relationship. One of the
things that Neo4j is really good at, is handling many interconnected
relationships.
• Let's build on the relationship that we just established, so that we can see
how easy it is to continue creating more nodes and relationships between
them. So we will create one more node and add two more relationships.
• We'll end up with the following graph:

This graph shows that Devin Townsend plays in the band, performed on the
album that the band released, and he also produced the album.
So let's start by creating the node for Devin Townsend:
CREATE (p:Person { Name: "Devin Townsend" })

Now create the relationships and return the graph:


MATCH (a:Artist),(b:Album),(p:Person)
WHERE [Link] = "Strapping Young Lad" AND [Link] = "Heavy
as a Really Heavy Thing" AND [Link] = "Devin Townsend"

10
CREATE (p)-[pr:PRODUCED]->(b), (p)-[pf:PERFORMED_ON]-
>(b), (p)-[pl:PLAYS_IN]->(a)
RETURN a,b,p

You should now see the graph as in the previous screenshot.

Create an Index using Cypher


• An index is a data structure that improves the speed of data retrieval
operations in a database. In Neo4j, you can create an index over a property on
any node that has been given a label. Once you create an index, Neo4j will
manage it and keep it up to date whenever the database is changed.
• To create an index, use the CREATE INDEX ON statement. Like this:
• CREATE INDEX ON :Album(Name)
• In the above example, we create an index on the Name property of all nodes
with the Album label.
• When the statement succeeds, the following message is displayed:

View the Index


• Indexes (and constraints) become part of the (optional) database schema. In the
Neo4j browser, you can review all indexes and constraints by using
the :schema command.
• Simply type this: :schema
• You will see a list of any indexes and constraints:

11
Index Hints
• Once an index has been created, it will automatically be used when you
perform relevant queries.
• However, Neo4j also allows you to enforce one or more indexes with a hint.
You can create an index hint by including USING INDEX ... in your query.
• So we could enforce the above index as follows:

MATCH (a:Album {Name: "Somewhere in Time"})


USING INDEX a:Album(Name)
RETURN a
• You can also provide multiple hints. Simply add a new USING INDEX for each
index you'd like to enforce.

Create a Constraint using Cypher


• A constraint allows you to place restrictions over the data that can be entered
against a node or a relationship.
• Constraints help enforce data integrity, because they prevent users from
entering the wrong kind of data. If a someone tries to enter the wrong kind of
data when a constraint has been applied, they will receive an error message.

Constraint Types
• In Neo4j, you can create uniqueness constraints and property existence
constraints.
• Uniqueness Constraint
Specifies that the property must contain a unique value (i.e. no two nodes
with an Artist label can share a value for the Name property.)
• Property Existence Constraint
Ensures that a property exists for all nodes with a specific label or for all
relationships with a specific type. Property existence constraints are only
available in the Neo4j Enterprise Edition.

Create a Uniqueness Constraint


• To create a uniqueness constraint in Neo4j, use the CREATE CONSTRAINT
ON statement. Like this:
CREATE CONSTRAINT ON (a:Artist) ASSERT [Link] IS UNIQUE
• In the above example, we create a uniqueness constraint on the Name
property of all nodes with the Artist label.
• When the statement succeeds, the following message is displayed:

12
View the Constraint
• Constraints (and indexes) become part of the (optional) database schema. We
can view the constraint we just created by using the :schema command. Like
this: :schema

• You will see the newly created constraint, as well as the index that was created
with it. We can also see the index that was created previously:

Test the Constraint


• You can test that the constraint actually works by attempting to create the
same artist twice.
• Run the following statement twice:
CREATE (a:Artist {Name: "Joe Satriani"})
RETURN a
• The first time you run it, the node will be created. The second time you run it,
you should receive the following error message:

Property Existence Constraints

13
• Property existence constraints can be used to ensure all nodes with a certain
label have a certain property. For example, you could specify that all nodes
labelled withArtist must contain a Name property.
• To create a property existence constraint, use theASSERT
exists([Link]) syntax.
Like this:

• CREATE CONSTRAINT ON ([Link]) ASSERT


exists([Link])

Selecting data with MATCH using Cypher


• Cypher's MATCH statement allows you to find data that matches a given
criteria. You can use MATCH to return the data or to perform some other
operation on it.
• The MATCH statement is used to match a given criteria, but it doesn't
actually return the data.
• To return any data from a MATCH statement, we still need to use the
RETURN clause.

Retrieve a Node
Example:
MATCH (p:Person)
WHERE [Link] = "Devin Townsend"
RETURN p
The WHERE clause works the same way as SQL's WHERE clause,
in that it allows you to narrow down the results by providing extra criteria.
However, you can achieve the same result without using a WHERE
clause. You can also search for a node by providing the same notation
you used to create the node.
The following code provides the same results as the above statement:

MATCH (p:Person {Name: "Devin Townsend"})


RETURN p

• Running either of the above queries will result in the following node being
displayed:

14
You may have noticed that clicking on a node expands an outer circle separated
into three sections — each representing a different option:

Clicking on the bottom section will expand the node's relationships:

15
Relationships
You can also traverse relationships with the MATCH statement. In fact, this
is one of the things Neo4j is really good at.
For example, if we wanted to find out which artist released the album called
Heavy as a Really Heavy Thing, we could use the following query:
MATCH (a:Artist)-[:RELEASED]->(b:Album)
WHERE [Link] = "Heavy as a Really Heavy Thing"
RETURN a
This will return the following node:

• You can see that the pattern we use in the MATCH statement is almost self-
explanatory. It matches all artists that released an album that had a name of
Heavy as a Really Heavy Thing.
• We use variables (i.e. a and b) so that we can refer to them later in the
query. We didn't provide any variables for the relationship, as we didn't need to
refer to the relationship later in the query.
• You might also notice that the first line uses the same pattern that we used
to create the relationship in the first place. This highlights the simplicity of the
Cypher language. We can use the same patterns in different contexts (i.e. to
create data and to retrieve data).

Return all Nodes


You can return all nodes in the database simply by omitting any filtering details.
Therefore, the following query will return all nodes in the database:
MATCH (n) RETURN n
This results in all our nodes being returned:

16
• You can also click on the Rows icon on the side to display the data in row format:

17
Limit the Results
Use LIMIT to limit the number of records in the output. It's a good idea to use
this when you're not sure how big the result set is going to be.
So we could simply append LIMIT 5 to the previous statement to limit the output
to 5 records:
MATCH (n) RETURN n
LIMIT 5

Skip the Results


It returns all the nodes in the db skipping the first 3 nodes.
MATCH(n) RETURN (n)
SKIP 3

Import Data from a CSV File using Cypher


• You can import data from a CSV (Comma Separated Values) file into a
Neo4j database. To do this, use the LOAD CSV clause.
• Being able to load CSV files into Neo4j makes it easy to import data from
another database model (for example, a relational database).
• With Neo4j, you can load CSV files from a local or remote URL.
• To access a file stored locally (on the database server), use a [Link] URL.
Otherwise, you can import remote files using any of the HTTPS, HTTP, and
FTP protocols.

Load a CSV File


Let's load a CSV file called [Link] using the HTTP protocol. It's not a large
file — it contains a list of 115 music genres, so it will create 115 nodes (and
230 properties).
This file is stored on [Link], so you can run this code from your Neo4j
browser and it should import directly into your database (assuming you are
connected to the Internet).
You can also download the file here: [Link]
LOAD CSV FROM
'[Link] AS line
CREATE (:Genre { GenreId: line[0], Name: line[1]})

Running the above statement should produce the following success message:

18
You can follow that up with a query to see the newly created nodes:
MATCH (n:Genre) RETURN n
Which should result in the nodes scattered around the data visualization frame:

Import a CSV file containing Headers


• The previous CSV file didn't contain any headers. If the CSV file contains
headers, you can use WITH HEADERS.
• Using this method also allows you to reference each field by their
column/header name.
• We have another CSV file, this time with headers. This file contains a list
of album tracks.
• Again, this one's not a large file — it contains a list of 32 tracks, so it will
create 32 nodes (and 96 properties).
• This file is also stored on [Link], so you can run this code from your

19
Neo4j browser and it should import directly into your database (assuming you
are connected to the Internet).
• You can also download the file here: [Link]

LOAD CSVWITH HEADERS FROM


'[Link] AS line
CREATE (:Track { TrackId: [Link], Name: [Link], Length: [Link]})
This should produce the following success message:

• Followed up with a query to view the newly created nodes:


MATCH (n:Track) RETURN n
• Which should result in the new nodes scattered around the data visualization frame.
• Click on the Rows icon to see each node and its three properties:

20
Custom Field Delimiter
You can specify a custom field delimiter if required. For example, you could
specify a semi-colon instead of a comma if that's how the CSV file is
formatted.
To do this, simply add the FIELDTERMINATOR clause to the statement. Like
this:
LOAD CSVWITH HEADERS FROM
'[Link] AS line
FIELDTERMINATOR ';'
CREATE (:Track { TrackId: [Link], Name: [Link], Length: [Link]})

Drop an Index using Cypher


• You can drop an index using the DROP INDEX ON statement. This will remove
the index from the database.
• So, to drop our previously created index, we can use the following statement:
DROP INDEX ON :Album(Name)
• When the statement succeeds, the following message is displayed:

21
View the Schema
You can now use the :schema command to verify that the applicable index has
been removed from the schema.
Simply type this:
:schema
You will see that the index is no longer in the schema:

Drop a Constraint using Cypher


You can drop a constraint using the DROP CONSTRAINT statement. This
will remove the constraint from the database, as well as its associated index.
So, to drop our previously created constraint (and its associated index), we
can use the following statement:
DROP CONSTRAINT ON (a:Artist) ASSERT [Link] IS UNIQUE
When the statement succeeds, the following message is displayed:

View the Schema


You can now use the :schema command to verify that the applicable
constraint (and its associated index) has been removed from the schema.
Simply type this:

22
:schema
You will see that the index is no longer in the schema:

Delete a Node using Cypher


To delete nodes and relationships using Cypher, use the DELETE clause.
The DELETE clause is used within the MATCH statement to delete whatever
data was matched.
So, the DELETE clause is used in the same place we used the RETURN clause
in our previous examples.
Example
The following statement deletes the Album node called
Killers:
MATCH (a:Album {Name: "Killers"}) DELETE a

Deleting Multiple Nodes


You can also delete multiple nodes in one go. Simply construct your MATCH
statement to include all nodes you'd like to delete.
MATCH (a:Artist {Name: "Iron Maiden"}),
(b:Album {Name: "Powerslave"})
DELETE a, b

Deleting All Nodes


You can delete all nodes from the database simply by omitting any filtering
criteria. Just like when we selected all nodes from the database,
you can delete them too.
MATCH (n) DELETE n

Deleting Nodes with Relationships


• There's one small catch with deleting nodes. And that is, you can only delete
nodes if they don't have any relationships. In other words, you must delete any
relationships before you delete the node itself.
• If you try to execute the above DELETE statement on nodes that have
relationships, you will see an error message like this:

23
This error message is telling us that we have to delete any relationships before we
delete the node.

Delete a Relationship using Cypher


• You can delete relationships in the same way as deleting odes — by matching
the relationship/s you want to delete.
• You can delete one or many relationships in one go. You can even delete all
relationships in the database.
• First, as a memory refresher, here are the relationships that we created earlier.

24
Let's delete the relationship of type RELEASED. There are several ways we could
go about this. Let's look at three.
The following statement is quite broad — it will delete all relationships
of type RELEASED:
MATCH ()-[r:RELEASED]-()
DELETE r
You could also be more specific and write something like this:
MATCH (:Artist)-[r:RELEASED]-(:Album)
DELETE r
The above statement will match all Artist nodes that have a relationship type of
RELEASED with an Album node.

You could be even more specific and do something like this:


MATCH (:Artist {Name: "Strapping Young Lad"})-[r:RELEASED]-
(:Album {Name: "Heavy as a Really Heavy Thing"})
DELETE r
Any of those statements will result in the RELEASED relationship being deleted.
The graph will look like this:

Deleting Nodes with Relationships Attached


Nodes can't be deleted if they still have relationships attached to them.
If we try to run the following statement:
MATCH (a:Artist {Name: "Strapping Young Lad"}) DELETE a
We will get the following error:

25
This is because that node has a relationship connected.
One option is to delete all relationships, then delete the node.

Another option is to use the DETACH DELETE clause.


The DETACH DELETE clause lets you delete a node and
all relationships connected to it.
So we can change the above statement to this:
MATCH (a:Artist {Name: "Strapping Young Lad"})
DETACH DELETE a
Running that statement will result in the following success message:

Delete the Whole Database


You can take the DETACH DELETE a step further and delete the whole database.
Simply remove any filtering criteria and it will delete all
nodes and all relationships.
Go ahead and execute the following statement:
MATCH (n) DETACH DELETE n
We no longer have any data in the database.

26
• Count( )
Count the employees whose salary is greater than 25000.
MATCH (n:employee)
where [Link]>25000
return count(n)
• Relationship
create (Dhawan: Player{name: “Shikhar Dhawan”, YOB:1985,
POB: “ Delhi”})
create (Ind: Country {name: “India”})
create (Dhawan)-[r:Batsman_of]->(Ind)
return Dhawan, Ind
• Creating relationship with label and properties
MATCH (a:Player),(b:Country) where [Link]=“Shikhar Dhawan” and
[Link]=“India”
create(a)-[r:Batsman_of {matches:5,Avg:90.75}]->(b)
return a,b
• Creating a complete path
create p=(Dhawan{name:“Shikhar Dhawan”})-[:Topscorer_of]-> (Ind
{name:“India”})-[:winnner_of]->(CT2013{name:“Champions Trophy
2013”})
return p
• Set property
MATCH(Dhawan:Player{name: “Shikhar Dhawan”, YOB:1985, POB:
“Delhi”})
SET [Link]=187
return Dhawan
• Set multiple property
SET [Link]=187, [Link]=2

• Removing a property using SET


MATCH (Jadeja:Player {name: “Ravindra Jadeja”, YOB=1988,
POB: “Navagam Ghed”})
SET [Link]=NULL
RETURN Jadeja
• Set label to existing node
MATCH (n{name: “James Anderson”, YOB=1982, POB:“Burnley”})
SET n :Player
RETURN n
• Removing property using remove
MATCH (Jadeja:Player {name: “Ravindra Jadeja”, YOB=1988,
POB: “Navagam Ghed”})
REMOVE [Link]

27
RETURN Jadeja

• Order by (runs scored by the player)


MATCH(n)
RETURN [Link], [Link]
ORDER BY [Link]
• Ordering nodes by multiple properties
MATCH(n)
RETURN(n)
ORDER BY [Link], [Link]
• Descending order
MATCH(n)
RETURN [Link], [Link]
ORDER BY [Link] desc

Consistency
• Since graph databases are operating on connected nodes, most graph database
solutions usually do not support distributing the nodes on different servers.
There are some solutions, however, that support node distribution across a
cluster of servers, such as Infinite Graph.
• Within a single server, data is always consistent, especially in Neo4J which is
fully ACID-compliant.
• When running Neo4Jin a cluster, a write to the master is eventually
synchronized to the slaves, while slaves are always available for read.
• Graph databases ensure consistency through transactions. They do not
allow dangling relationships: The start node and nd node always have to exist,
and nodes can only be deleted if they don’t have any relationships attached
to them.

Transactions
• Neo4J is ACID-compliant. Before changing any nodes or adding any
relationships to existing nodes, we have to start a transaction.
• Without wrapping operations in transactions, we will get a
NotInTransactionException. Read operations can be done without initiating a
transaction.

Transaction transaction = [Link]();


try {
Node node = [Link]();
[Link]("name", "NoSQL Distilled");
[Link]("published", "2012");
[Link]();
28
} finally {
[Link]();
}

• In the above code, we started a transaction on the database, then created a


node and set properties on it. We marked the transaction as success and finally
completed it by finish.
• A transaction has to be marked as success, otherwise Neo4J assumes that it
was a failure and rolls it back when finish is issued.
• Setting success without issuing finish also does not commit the data to the
database.
• This way of managing transactions has to be remembered when developing,
as it differs from the standard way of doing transactions in an RDBMS.

Availability
• Neo4J, as of version 1.8, achieves high availability by providing for
replicated slaves.
• These slaves can also handle writes: When they are written to, they
synchronize the write to the current master, and the write is committed first at
the master and then at the slave. Other slaves will eventually get the update.
• Other graph databases, such as Infinite Graph and FlockDB, provide for
distributed storage of the nodes.
• Neo4J uses the Apache ZooKeeper[ZooKeeper] to keep track of the last
transaction IDs persisted on each slave node and the current master node.
Once a server starts up, it communicates with ZooKeeper and finds out which
server is the master. If the server is the first one to join the cluster, it becomes
the master; when a master goes down, the cluster elects a master from the
available nodes, thus providing high availability.

Query Features
• Neo4J has the Cypher [Cypher] query language for querying the graph. Neo4J
allows you to query the graph for properties of the nodes, traverse the graph, or
navigate the nodes relationships using language bindings.
• Properties of a node can be indexed using the indexing service. Similarly,
properties of relationships or edges can be indexed, so a node or edge can be
found by the value.
• Indexes should be queried to find the starting node to begin a traversal. Let’s
look at searching for the node using node indexing.

29
• If we have the graph shown in Figure, we can index the nodes as they are
added to the database, or we can index all the nodes later by iterating over
them. We first need to create an index for the nodes using the IndexManager.
• Index<Node>nodeIndex = [Link]().forNodes("nodes");
• We are indexing the nodes for the name property. Neo4J uses Lucene
[Lucene] as its indexing service.

Transaction transaction = [Link]();


try {
Index<Node>nodeIndex = [Link]().forNodes("nodes");
[Link](martin, "name", [Link]("name"));
[Link](pramod, "name", [Link]("name"));
[Link]();
} finally {
[Link]();
}
• Adding nodes to the index is done inside the context of a transaction. Once the
nodes are indexed, we can search them using the indexed property.
• If we search for the node with the name of Barbara, we would query the
index for the property of name to have a value of Barbara.
Node node = [Link]("name", "Barbara").getSingle();

• We get the node whose name is Martin; given the node, we can get all its
relationships.
Node martin = [Link]("name",
"Martin").getSingle();
allRelationships = [Link]();
• We can get both INCOMING or OUTGOING relationships.
30
incomingRelations=
[Link]([Link]);

• We can also apply directional filters on the queries when querying for a
relationship.
• If we want to find all people who like NoSQL Distilled, we can find the
NoSQL Distilled node and then get its relationships with [Link].
• At this point we can also add the type of relationship to the query filter, since
we are looking only for nodes that LIKE NoSQL Distilled.
Node nosqlDistilled = [Link]("name", "NoSQL
Distilled").getSingle();
relationships = [Link](INCOMING,LIKES);
for (Relationship relationship : relationships) {
[Link]([Link]());
}

• Graph databases are really powerful when you want to traverse the graphs
at any depth and specify a starting node for the traversal. This is especially
useful when you are trying to find nodes that are related to the starting node
at more than one level down.
• As the depth of the graph increases, it makes more sense to traverse the
relationships by using a Traverser where you can specify that you are looking
for INCOMING, OUTGOING, or BOTH types of relationships.
• You can also make the traverser go top-down or sideways on the raph by using
Order values of BREADTH_FIRST or DEPTH_FIRST.
• The traversal has to start at some node—in this example, we try to find all the
nodes at any depth that are related as a FRIEND with Barbara:
Node barbara = [Link]("name",
"Barbara").getSingle();
Traverser friendsTraverser =
[Link](Order.BREADTH_FIRST,
StopEvaluator.END_OF_GRAPH,
ReturnableEvaluator.ALL_BUT_START_NODE,
[Link],
[Link]);
• The friendsTraverser provides us a way to find all the odes that are related
to Barbara where the relationship type is FRIEND.
• The nodes can be at any depth—friend of a friend at any level—allowing
you to explore tree structures.

31
• One of the good features of graph databases is finding paths between two
nodes—determining if there are multiple paths, finding all of the paths or the
shortest path.
• In the graph in Figure, we know that Barbara is connected to Jill by two distinct
paths; to find all these paths and the distance between Barbara and Jill along
those different paths, we can use

Node barbara = [Link]("name", "Barbara").getSingle();


Node jill = [Link]("name", "Jill").getSingle();
PathFinder<Path> finder = [Link](
[Link](FRIEND,[Link])
,MAX_DEPTH);
Iterable<Path> paths = [Link](barbara, jill);

• This feature is used in social networks to show relationships between any two
nodes. To find all the paths and the distance between the nodes for each path, we
first get a list of distinct paths between the two nodes.
• The length of each path is the number of hops on the graph needed to reach the
destination node from the start node. Often, you need to get the shortest path
between two nodes; of the two paths from Barbara to Jill, the shortest path can be
found by using
PathFinder<Path> finder = [Link](
[Link](FRIEND,
[Link]) , MAX_DEPTH);
Iterable<Path> paths = [Link](barbara, jill);

• Many other graph algorithms can be applied to the graph at hand, such as
Dijkstra’s algorithm[Dijkstra’s] for finding the shortest or cheapest path between
nodes.
START beginingNode = (beginning node specification)
MATCH (relationship, pattern matches)
WHERE (filtering condition: on data in nodes and
relationships)
RETURN (What to return: nodes, relationships, properties)
ORDER BY (properties to order by)
SKIP (nodes to skip from top)
LIMIT (limit results)

Scaling
• In NoSQL databases, one of the commonly used scaling techniques is
sharding, where data is split and distributed across different servers. With graph

32
databases, sharding is difficult, as graph databases are not aggregate-oriented
but relationship-oriented.
• Since any given node can be related to any other node, storing related nodes
on the same server is better for graph traversal. Traversing a graph when
the nodes are on different machines is not good for performance. Knowing
this limitation of the graph databases, we can still scale them using some common
techniques.
• Generally speaking, there are three ways to scale graph databases. Since
machines now can come with lots of RAM, we can add enough RAM to the
server so that the working set of nodes and relationships is held entirely in
memory. This technique is only helpful if the dataset that we are working
with will fit in a realistic amount of RAM.

• We can improve the read scaling of the database by adding more slaves with
read-only access to the data, with all the writes going to the master. This pattern
of writing once and reading from many servers is a proven technique in
MySQL clusters and is really useful when the dataset is large enough
to not fit in a single machine’s RAM, but small enough to be replicated across
multiple machines.
• When the dataset size makes replication impractical, we can shard the data
from the application side using domain specific knowledge.
• For example, nodes that relate to the North America can be created on one
server while the nodes that relate to Asia on another.
• This application-level sharding needs to understand that nodes are stored on
physically different databases.

Figure: Application-level sharding of nodes

33
Suitable Use Cases

Connected Data
Social networks are where graph databases can be deployed and used very
effectively. These social graphs don’t have to be only of the friend kind; for
example, they can represent employees, their knowledge, and where they
worked with other employees on different projects. Any link-rich domain is
well suited for graph databases.

Recommendation Engines
As nodes and relationships are created in the system, they can be used to make
recommendations like “your friends also bought this product” or “when
invoicing this item, these other items are usually invoiced.”

Routing, Dispatch, and Location-Based Services


• Every location or address that has a delivery is anode, and all the nodes where
the delivery has to be made by the delivery person can be modeled as a graph of
nodes. Relationships between nodes can have the property of distance, thus
allowing you to deliver the goods in an efficient manner.
• Distance and location properties can also be used in graphs of places of interest,
so that your application can provide recommendations of good restaurants or
entertainment options nearby.

When Not to Use


34
• In some situations, graph databases may not appropriate. When you want to
update all or a subset of entities—for example, in an analytics solution where
all entities may need to be updated with a changed property—graph databases
may not be optimal since changing a property on all the nodes is not a
straightforward operation.
• Even if the data model works for the problem domain, some databases may be
unable to handle lots of data, especially in global graph operations (those
involving the whole graph).

35

You might also like