Making Graph Databases Fun Again With Java
Graph databases need to be made fun again! Not to worry — the open-source TinkerPop from Apache is here to do just that.
Join the DZone community and get the full member experience.
Join For FreeNoSQL databases have become more popular in several areas. NoSQL has many different uses, including graph use cases. The graph database has a structure pretty different from relational technology and has a lot of successful cases, such as recommendation systems on Facebook and LinkedIn. This article will cover what a graph database is and how to use it with Java.
The Graph Structure
- Property: A small component in the structure; a tuple where the key is the name and the value is the information itself.
- Vertex: Looks like the table in a SQL technology that has an unlimited number of properties.
- Edge: The element that represents the relationship between vertices; it has a small similarity with a relationship in SQL. However, the edge has properties — so a connection deeper than relational technology.
The graph direction is another concept pretty important in a graph structure, i.e. you can know a person despite this person not knowing you.
Out: Vertex > action > vertex; the "out" is the "action" direction, moreover the sample (i.e. I know the Ironman)
In: Vertex > passive; the "in" is the reaction course; synonymously, the Ironman is known by me.
The Graph Databases Providers
There are several graphs; the most famous one is Neo4j.
Neo4j
ArangoDB
Titan
OrientDB
The APIs
The biggest issue when the market has several solutions is the several ways to connecting using API, so each NoSQL provider has itself own solution to connect to the database. So, there is a locking, and every time we need to learn a different API, thereby, the cust to chance is high.
TinkerPop
To avoid locking and the previously related problem, we have TinkerPop. TinkerPop is an open-source solution from Apache Foundation. It's a standard API to do graph database operations and includes a nice graph query. Currently, the TinkerPop has more than 30 databases implemented.
Graph Over Relational Technology
Take the picture below; the goal is to through a hierarchical structure such as a food chain.
What can we do in a relational technology? If you're using a graph, that just became easier. Running gremlin, a TinkerPop query, the command is:
g.V().repeat(out("eats")).times(3);//to go three times in the graph
g.V().repeat(out("eats")) .until(has("name", "grass"));//to go as a "do while" structure
That easy, isn't?
Nice, but How About My Entities?
TinkerPop does support Java, however, just with its API, and that is not even close to the entities such as Person and Book with which Java developers work.
JNoSQL
This is why we launched the Eclipse JNoSQL project: a flexible and extensible Java API for connecting to NoSQL databases. With its easy-to-use interface and support to multiple NoSQL models, JNoSQL brings to the Java developer the easy of use and freedom of choice that are characteristic of a Java ecosystem.
JNoSQL supports all the NoSQL models, like key-value, column family, document-oriented, and graph databases. This allows developers to experiment with multiple NoSQL databases and choose the ones that are better-suited to their particular needs. It frees developers from having to commit to a single product and gives vendors the freedom to innovate without alienating developers.
With support for more than thirty NoSQL databases and integrating with CDI, JNoSQL has quickly become a central integration piece to deal with NoSQL databases in Java.
The project has two layers:
The communication API, known as Diana: An API to communicate with the database, similar to JDBC for SQL databases. This API has four specializations — one for each kind of database.
The mapping API, known as Artemis: An API to map the data in the database to Java Objects, providing similar functionality to JPA for relational databases. It is annotation and CDI driven and has integration with other technologies such as Bean Validation.
JNoSQL and Graph
In the Graph database, JNoSQL has an integration with TinkerPop through the mapping API, AKA Artemis. Let's see how to make the graph below a Java operation...
Create the Entity With the Mapping Annotation
@Entity
public class Book {
@Id
private Long id;
@Column
private String name;
//getter and setter
}
@Entity
public class Person {
@Id
private Long id;
@Column
private String name;
@Column
private int age;
@Column
private String occupation;
@Column
private Double salary;
//getter and setter
}
Inject the GraphTemplate Class
@Inject
private GraphTemplate graph;
//to CDI 2.0 with Java SE
GraphTemplate graph = container.select(GraphTemplate.class).get();
Save the Entities
Person poliana = Person.builder().withName("Poliana").withAge(25).build();
Book shack = Book.builder().withAge(2007).withName("The Shack").build();
graphTemplate.insert(poliana);
graphTemplate.insert(shack);
Create the Relationship Between Them (Edge)
EdgeEntity<Person, Book> reads = graphTemplate.edge(poliana, "reads", shack);
reads.add("where", "Brazil");
Done! We have our first graph operation.
Running Queries With JNoSQL and TinkerPop
In our scenario, we're working on a marketing camping and our target is:
An engineer
The salary is higher than $3,000
The age is between 20 and 25 years old
//In this scenario both SQL and Tinkerpop easy to do.
List<Person> developers = graph.getTraversalVertex()
.has("salary", gte(3_000D))
.has("age", between(20, 25))
.has("occupation", "Developer")
.<Person>stream().collect(toList());
The Engineer's Friends
Once we have our target, the engineer, we want to return the engineer friends. On this next step, TinkerPop became easier than SQL. We'll keep all the previous parameters with a new parameter query, out("knows")
.
List<Person> result = graph.getTraversalVertex()
.has("salary", gte(3_000D))
.has("age", between(20, 25))
.has("occupation", "Developer")
.out("knows");
The Engineer's Love
The fact is that the target knows a person isn't enough anymore; we want deeper details into the relationship. That is the power of a graph database. With TinkerPop, we just need to replace the last parameter to outE("knows")
. The difference that is we're mapping the Edge element so we can do condition on edge properties based, in this case, if the knows
label has felt love.
List<Person> love = graph.getTraversalVertex()
.has("salary", gte(3_000D))
.has("age", between(20, 25))
.has("occupation", "Developer")
.outE("knows")
.has("feel", "love")
.bothV()
.<Person>stream()
.distinct()
.collect(toList());
References
Opinions expressed by DZone contributors are their own.
Comments