In parts 1 & 2 we covered setting up and testing GraphQL APIs. In this article, we will be looking into querying graph DB which is Neo4j in our case. For querying, we will be using the Neo4j OGM library and spring data’s Neo4jRepository.

Neo4j OGM

An OGM (Object Graph Mapper) maps nodes and relationships in the graph to objects and references in a domain model. Much like JPA, Neo4j-OGM allows you to annotate your POJOs in order to map them to nodes, relationships, and properties in the graph. In the previous blog, we used annotations like NodeEntity, Relationship, RelationshipEntity, StartNode, and EndNode, all these are part of the OGM library. It supports multiple drivers BOLT, HTTP, and embedded. But we have used BOLT driver as it is a fast native driver that communicates over BOLT protocol. The default PORT to connect Neo4J using bolt protocol is 7687. The following dependencies are required to be included in pom.xml:

This will include neo4j OGM and its dependent libraries as well as spring data capabilities which are built on top of Neo4J OGM library.

Session Factory and Session

On the successful startup of the server, the SessionFactory object is created at the backend. Using this object we acquire session class objects to fire custom queries at runtime. In one of the use cases, the DB query couldn’t be determined beforehand like a search member. In search member, we don’t know what all parameters can come in request it could range from 1 to 5 which makes it hard to create queries for every combination. So the solution was to create query at runtime dynamically and then execute it using Session object. Following is the code sample:

String cypher = “MATCH (m:Member {%bedrockmember%}) \n” +

” OPTIONAL MATCH(m:Member)-[r2:REPORTS_TO]->(p2:Member)-[r3:REPORTS_TO]-(p3:Member) \n”+
” OPTIONAL MATCH (m)-[ar:CREATED_ASSET]->(a:Assets) ” +
” OPTIONAL MATCH (m:Member)-[sr:KNOWS_SKILLS]->(s:Skill)” +
” OPTIONAL MATCH (m:Member)-[cr:IS_CERTIFIED_IN]->(c:Certifications)” +
” OPTIONAL MATCH (m:Member)-[pr:IS_BILLED_FOR]->(p:Project)\n” +
” OPTIONAL MATCH (m:Member)-[hc:HAS_CONTRIBUTION]->(co:Contributions)\n” +
” RETURN m,ar,a,sr,s,cr,c,pr,p,hc,co,r2,p2,p3,r3″;

cypher = cypher.replace(“%bedrockmember%”, buildQuery);

Result memberList = sessionFactory.openSession().query(cypher, params);

Spring Data Neo4j Repository

Spring Data Neo4j uses Neo4-OGM to help the rapid and easy development of spring applications. It is very useful in querying the DB with features same as any other ORM framework like Hibernate or JPA. Two core components that are used in development are Neo4jRepository and Neo4jTransactionManager. As the name suggests extending Neo4jRepository enables with all kinds of CRUD, pagination, sorting, etc. operations and Neo4jTransactionManager is used to manage transactions.

The above image shows an example of the @Repository class which is extending the Neo4jRepository. The 2 most common ways for querying DB are shown in the example. The first 2 methods i.e. line number 14 & 16 are an example of querying using the find methods. These are very powerful as in these we can find by properties or we can use a combination of AND and OR between the properties. Also, we can use various keywords like “GreaterThan”, “LessThan”, “NotNull”, “Like” etc. For all supported keywords you can check this link In the second method of example, we are fetching members having experience greater than specified param. All find methods execute Cypher queries at the backend. The last 2 methods i.e. line number 19 & 22 are a way of defining your own Cypher queries. Queries using the Cypher graph query language can be supplied with the @Query annotation.

Pagination and Sorting

SDN has support for sorting and pagination while querying, in order to do that we need to supply Sort or Pageable class objects to repository methods. Following is an example:

Service Class:

memberRepository.findAllMemberWithSkill(skill,PageRequest.of(0, 10, Sort.Direction.DESC, “experience“));

Repository Class

@Query(“MATCH (m:Member)-[b:KNOWS_SKILLS]-(p:Skill) where m.skillBucket = $skill RETURN m”)
List<Member> findAllMemberWithSkill(String skill, PageRequest pageRequest);

In the above example, we are fetching member records who knows a skill with page 0 and size 10. Also, it is sorted in descending order to list the most experienced person in some specific skill on top.

To  Be Continued….

In this article, we learned how to query Neo4j DB using 2 different libraries Noe4j OGM and Spring Data for Neo4j (SDN). We also got a sneak peek of Session factory, session, pagination, and sorting. Now that we are done with setting up the project and playing with data. In the next article, we will be looking into using Kong as an API gateway for the application.