Neo4j With Scala: An Introduction
Are you a Scala user who's interested in getting started with Neo4j? Look no further!
Join the DZone community and get the full member experience.
Join For FreeWhen we use a relational database for storing data, we store data in predefined tables and then define foreign keys for references between tables or rows. But when it comes to graph databases, we store data in nodes and relationships. Graph databases provide us with flexibility to arrange data in an easy way.
When transforming a data model from a Relational Database Management System (RDBMS) to a graph database, here are some transformations we'll need to make:
- Tables are represented by labels on nodes.
- Rows in an entity table become nodes.
- Columns on those tables become node properties.
- Remove technical primary keys and keep business primary keys.
- Add unique constraints for business primary keys and add indexes for frequent lookup attributes.
- Replace foreign keys with relationships to the other table and remove them afterwards.
- Remove data with default values — no need to store those.
- Data in tables that are denormalized and duplicated might have to be pulled out into separate nodes to get a cleaner model.
- Indexed column names might indicate an array property.
- JOIN tables are transformed into relationships and columns on those tables become relationship properties.
When we want to transform our data model from a relational database, it is very important that we know about these terms and the graph data model.
We used SQL statements there for interacting with the database, and here we used Cypher statement for the same.
SQL Statement:
SELECT c.customer_id , c.customer_name FROM customer AS c WHERE c.customer_city = 'Delhi';
Cypher Statement:
Match (c: customer)
WHERE c.customer_city = 'Delhi'
RETURN c.customer_id , c.customer_name ;
Same and boring, we can write Cypher like this:
Match (c: customer{customer_city : 'Delhi'})
RETURN c.customer_id , c.customer_name ;
Now we see how we can use Scala with Neo4j. To use Neo4j, we can use neo4j-java-driver for creating Driver and Session:
libraryDependencies += "org.neo4j.driver" % "neo4j-java-driver" % "1.0.4"
Create Driver and Session:
val driver = GraphDatabase.driver("bolt://localhost/7687", AuthTokens.basic("neo4j", "neo4j"))
val session = driver.session
In Neo4j, we use the Bolt protocol. It is based on PackStream serialization and supports protocol versioning, authentication, and TLS via certificates.
Now we can create a case class where we can define its value. Here, we have a case class:
case class User(name: String, last_name: String, age: Int, city: String)
Now for the CRUD operation:
Create a Node :
val script = s"CREATE (user:Users {name:'${user.name}',last_name:'${user.last_name}',age:${user.age},city:'${user.city}'})"
val result = session.run(script)
Retrieve all Node :
val script = s"MATCH (user:Users) RETURN user.name AS name, user.last_name AS last_name, user.age AS age, user.city AS city"
val result = session.run(script)
Update a Node :
val script = s"MATCH (user:Users) where user.name ='$name' SET user.name = '$newName' RETURN user.name AS name, user.last_name AS last_name, user.age AS age, user.city AS city"
val result = session.run(script)
Delete a Node :
val script = s"MATCH (user:Users) where user.name ='$name' Delete user"
val result = session.run(script)
Now, we can create relationships between the nodes. We implement a method that takes a user's name and uses a list of those users' names with whom we want to create relation and relation_type (i.e. Friend, Family). We modify the list in a comma-separated ( “\”, \””) string and pass that in a script.
val nameOfFriends = "\"" + userList.mkString("\", \"") + "\""
val script = s"MATCH (user:Users {name: '${user_name}'}) FOREACH (name in [${nameOfFriends}] | CREATE (user)-[:$relation_name]->(:Users {name:name}))"
session.run(script)
Here, we send a user's name "Anurag," a list of Friends ("Sandy," "Manish," "Shivansh"), and set the relation between them as "Friends."
Now, we create two more nodes as friends of "Sandy."
And now we want to know the Friends of Friends. Here is the Cypher:
val script = s"MATCH (user:Users)-[:$relation_name]-(friend:Users)-[:$relation_name]-(foaf:Users) WHERE user.name = '$user_name' AND NOT (user)-[:$relation_name]-(foaf) RETURN foaf"
session.run(script)
For deleting all relations' records, we can use this Cypher:
val script = s"MATCH (n)-[relation:$relation_name]->(r) DELETE relation"
session.run(script)
I hope this will help you to start with graph databases (Neo4j).
You can get the above working example from the GitHub repo.
Published at DZone with permission of Anurag Srivastava, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments