designing and building a graph database application - ian robinson (neo technology)
DESCRIPTION
Presented at JAX London In this session we'll look at some of the design and implementation strategies you can employ when building a Neo4j-based graph database solution, including architectural choices, data modelling, and testing.TRANSCRIPT
![Page 1: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/1.jpg)
Twi$er: @ianSrobinson #neo4j
Designing and Building a Graph Database Applica5on
![Page 2: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/2.jpg)
Roadmap
• Complex data • Designing a graph data model and queries • Tes@ng
![Page 3: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/3.jpg)
complexity = f(size, semi-structure, connectedness)
Data Complexity
![Page 4: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/4.jpg)
Social Network
![Page 5: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/5.jpg)
Network Impact Analysis
![Page 6: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/6.jpg)
Route Finding
![Page 7: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/7.jpg)
Recommenda@ons
![Page 8: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/8.jpg)
Logis@cs
![Page 9: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/9.jpg)
Access Control
![Page 10: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/10.jpg)
Fraud Analysis
![Page 11: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/11.jpg)
Securi@es and Debt
Image: orgnet.com
![Page 12: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/12.jpg)
Graphs Are Everywhere
![Page 13: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/13.jpg)
Graph Databases
• Store • Manage • Query data
![Page 14: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/14.jpg)
Neo4j is a Graph Database
![Page 15: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/15.jpg)
Labeled Property Graph
![Page 16: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/16.jpg)
Designing a Graph Model
![Page 17: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/17.jpg)
Models
Images: en.wikipedia.org
Purposeful abstrac@on of a domain designed to sa@sfy par@cular applica@on/end-‐user goals
![Page 18: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/18.jpg)
Applica@on/End-‐User Goals
As an employee
I want to know who in the company has similar skills to me
So that we can exchange knowledge
![Page 19: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/19.jpg)
Ques@ons To Ask of the Domain
Which people, who work for the same company as me, have similar skills to me?
As an employee I want to know who in the company has similar skills to me So that we can exchange knowledge
![Page 20: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/20.jpg)
Iden@fy En@@es
Which people, who work for the same company as me, have similar skills to me? Person Company Skill
![Page 21: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/21.jpg)
Iden@fy Rela@onships Between En@@es
Which people, who work for the same company as me, have similar skills to me? Person WORKS_FOR Company Person HAS_SKILL Skill
![Page 22: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/22.jpg)
Convert to Cypher Paths
Person WORKS_FOR Company Person HAS_SKILL Skill
Rela@onship
Label
(:Person)-[:WORKS_FOR]->(:Company),(:Person)-[:HAS_SKILL]->(:Skill)
![Page 23: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/23.jpg)
Consolidate Paths
(:Person)-[:WORKS_FOR]->(:Company),(:Person)-[:HAS_SKILL]->(:Skill)
(:Company)<-[:WORKS_FOR]-(:Person)-[:HAS_SKILL]->(:Skill)
![Page 24: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/24.jpg)
Candidate Data Model
(:Company)<-[:WORKS_FOR]-(:Person)-[:HAS_SKILL]->(:Skill)
![Page 25: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/25.jpg)
Express Ques@on as Graph Pa$ern
Which people, who work for the same company as me, have similar skills to me?
![Page 26: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/26.jpg)
Cypher Query
Which people, who work for the same company as me, have similar skills to me? MATCH (company)<-[:WORKS_FOR]-(me:Person)-[:HAS_SKILL]->(skill), (company)<-[:WORKS_FOR]-(colleague)-[:HAS_SKILL]->(skill)WHERE me.name = {name}RETURN colleague.name AS name, count(skill) AS score, collect(skill.name) AS skillsORDER BY score DESC
![Page 27: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/27.jpg)
Graph Pa$ern
Which people, who work for the same company as me, have similar skills to me? MATCH (company)<-[:WORKS_FOR]-(me:Person)-[:HAS_SKILL]->(skill), (company)<-[:WORKS_FOR]-(colleague)-[:HAS_SKILL]->(skill)WHERE me.name = {name}RETURN colleague.name AS name, count(skill) AS score, collect(skill.name) AS skillsORDER BY score DESC
![Page 28: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/28.jpg)
Which people, who work for the same company as me, have similar skills to me? MATCH (company)<-[:WORKS_FOR]-(me:Person)-[:HAS_SKILL]->(skill), (company)<-[:WORKS_FOR]-(colleague)-[:HAS_SKILL]->(skill)WHERE me.name = {name}RETURN colleague.name AS name, count(skill) AS score, collect(skill.name) AS skillsORDER BY score DESC
Anchor Pa$ern in Graph
Search nodes labeled ‘Person’, matching on
‘name’ property
![Page 29: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/29.jpg)
Create Projec@on of Results
Which people, who work for the same company as me, have similar skills to me? MATCH (company)<-[:WORKS_FOR]-(me:Person)-[:HAS_SKILL]->(skill), (company)<-[:WORKS_FOR]-(colleague)-[:HAS_SKILL]->(skill)WHERE me.name = {name}RETURN colleague.name AS name, count(skill) AS score, collect(skill.name) AS skillsORDER BY score DESC
![Page 30: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/30.jpg)
First Match
![Page 31: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/31.jpg)
Second Match
![Page 32: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/32.jpg)
Third Match
![Page 33: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/33.jpg)
Running the Query
+-----------------------------------+| name | score | skills |+-----------------------------------+| "Lucy" | 2 | ["Java","Neo4j"] || "Bill" | 1 | ["Neo4j"] |+-----------------------------------+2 rows
![Page 34: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/34.jpg)
From User Story to Model and Query
MATCH (company)<-[:WORKS_FOR]-(me:Person)-[:HAS_SKILL]->(skill), (company)<-[:WORKS_FOR]-(colleague)-[:HAS_SKILL]->(skill)WHERE me.name = {name}RETURN colleague.name AS name, count(skill) AS score, collect(skill.name) AS skillsORDER BY score DESC
As an employee I want to know who in the company has similar skills to me So that we can exchange knowledge
(:Company)<-[:WORKS_FOR]-(:Person)-[:HAS_SKILL]->(:Skill)
Person WORKS_FOR Company Person HAS_SKILL Skill
?Which people, who work for the same company as me, have similar skills to me?
![Page 35: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/35.jpg)
Tes@ng
![Page 36: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/36.jpg)
Why Test?
• Ensure model is fit for queries – Rapid feedback
• Ensure correctness of queries • Document your understanding of your domain – Including corner cases and excep@ons
• Provide a regression test suite – Allows you to change and evolve model and queries
![Page 37: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/37.jpg)
Method
• Develop queries, or classes that encapsulate queries, using unit tests
• Use small, well-‐understood datasets in each test – Create data in test setup – Test dataset expresses your understanding of (part of) the domain
• Inject in-‐memory graph database (or Cypher engine) into object under test
• The exact strategy you use depends on your applica@on architecture…
![Page 38: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/38.jpg)
Applica@on Architectures
• Embedded • Server • Server with Extensions
![Page 39: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/39.jpg)
Applica@on Architectures
• Embedded – Host in Java process – Access to Java APIs
• Server • Server with Extensions
Java APIs
Applica@on
![Page 40: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/40.jpg)
Applica@on Architectures
• Embedded • Server – HTTP/JSON interface – Server wraps embedded instance
• Server with Extensions
REST API REST API REST API
REST Client
Applica@on
Write LB Read LB
![Page 41: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/41.jpg)
Applica@on Architectures
• Embedded • Server • Server with Extensions – Execute complex logic on server – Control HTTP request/response format
REST API Extensions
![Page 42: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/42.jpg)
Embedded Example
• Company social network • Find colleagues with similar skills • Encapsulate query in a ColleagueFinder
![Page 43: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/43.jpg)
Unit Test Fixture
public class ColleagueFinderTest { private GraphDatabaseService db; private ColleagueFinder finder; @Before public void init() { db = new TestGraphDatabaseFactory().newImpermanentDatabase(); ExampleGraph.populate( db ); finder = new ColleagueFinder( new ExecutionEngine( db ) ); } @After public void shutdown() { db.shutdown(); }}
![Page 44: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/44.jpg)
Create Database
public class ColleagueFinderTest { private GraphDatabaseService db; private ColleagueFinder finder; @Before public void init() { db = new TestGraphDatabaseFactory().newImpermanentDatabase(); ExampleGraph.populate( db ); finder = new ColleagueFinder( new ExecutionEngine( db ) ); } @After public void shutdown() { db.shutdown(); }}
![Page 45: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/45.jpg)
Populate Graph
public class ColleagueFinderTest { private GraphDatabaseService db; private ColleagueFinder finder; @Before public void init() { db = new TestGraphDatabaseFactory().newImpermanentDatabase(); ExampleGraph.populate( db ); finder = new ColleagueFinder( new ExecutionEngine( db ) ); } @After public void shutdown() { db.shutdown(); }}
![Page 46: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/46.jpg)
Create Object Under Test
public class ColleagueFinderTest { private GraphDatabaseService db; private ColleagueFinder finder; @Before public void init() { db = new TestGraphDatabaseFactory().newImpermanentDatabase(); ExampleGraph.populate( db ); finder = new ColleagueFinder( new ExecutionEngine( db ) ); } @After public void shutdown() { db.shutdown(); }}
Inject Execu@onEngine
![Page 47: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/47.jpg)
ImpermanentGraphDatabase
• In-‐memory • For tes@ng only, not produc@on! <dependency> <groupId>org.neo4j</groupId> <artifactId>neo4j-kernel</artifactId> <version>${project.version}</version> <type>test-jar</type> <scope>test</scope> </dependency>
![Page 48: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/48.jpg)
Create Sample Data
public static void populate( GraphDatabaseService db ) { ExecutionEngine engine = new ExecutionEngine( db ); String cypher = "CREATE ian:Person VALUES {name:'Ian'},\n" + " bill:Person VALUES {name:'Bill'},\n" + " lucy:Person VALUES {name:'Lucy'},\n" + " acme:Company VALUES {name:'Acme'},\n" + // Cypher continues... " (bill)-[:HAS_SKILL]->(neo4j),\n" + " (bill)-[:HAS_SKILL]->(ruby),\n" + " (lucy)-[:HAS_SKILL]->(java),\n" + " (lucy)-[:HAS_SKILL]->(neo4j)"; engine.execute( cypher );}
![Page 49: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/49.jpg)
Unit Test
@Testpublic void shouldFindColleaguesWithSimilarSkills() throws Exception { // when Iterator<Map<String, Object>> results = finder.findColleaguesFor( "Ian" ); // then assertEquals( "Lucy", results.next().get( "name" ) ); assertEquals( "Bill", results.next().get( "name" ) ); assertFalse( results.hasNext() );}
![Page 50: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/50.jpg)
Execute Object Under Test
@Testpublic void shouldFindColleaguesWithSimilarSkills() throws Exception { // when Iterator<Map<String, Object>> results = finder.findColleaguesFor( "Ian" ); // then assertEquals( "Lucy", results.next().get( "name" ) ); assertEquals( "Bill", results.next().get( "name" ) ); assertFalse( results.hasNext() );}
![Page 51: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/51.jpg)
Assert Results
@Testpublic void shouldFindColleaguesWithSimilarSkills() throws Exception { // when Iterator<Map<String, Object>> results = finder.findColleaguesFor( "Ian" ); // then assertEquals( "Lucy", results.next().get( "name" ) ); assertEquals( "Bill", results.next().get( "name" ) ); assertFalse( results.hasNext() );}
![Page 52: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/52.jpg)
Ensure No More Results
@Testpublic void shouldFindColleaguesWithSimilarSkills() throws Exception { // when Iterator<Map<String, Object>> results = finder.findColleaguesFor( "Ian" ); // then assertEquals( "Lucy", results.next().get( "name" ) ); assertEquals( "Bill", results.next().get( "name" ) ); assertFalse( results.hasNext() );}
![Page 53: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/53.jpg)
ColleagueFinder
public class ColleagueFinder { private final ExecutionEngine executionEngine; public ColleagueFinder( ExecutionEngine executionEngine ) { this.executionEngine = executionEngine; } public Iterator<Map<String, Object>> findColleaguesFor( String name ) { ... }}
![Page 54: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/54.jpg)
Inject Execu@onEngine
public class ColleagueFinder { private final ExecutionEngine executionEngine; public ColleagueFinder( ExecutionEngine executionEngine ) { this.executionEngine = executionEngine; } public Iterator<Map<String, Object>> findColleaguesFor( String name ) { ... }}
![Page 55: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/55.jpg)
findColleaguesFor() Method
public Iterator<Map<String, Object>> findColleaguesFor( String name ) { String cypher = "MATCH (me:Person)-[:WORKS_FOR]->(company),\n" + " (me)-[:HAS_SKILL]->(skill),\n" + " (colleague)-[:WORKS_FOR]->(company),\n" + " (colleague)-[:HAS_SKILL]->(skill)\n" + "WHERE me.name = {name}\n" + "RETURN colleague.name AS name,\n" + " count(skill) AS score,\n" + " collect(skill.name) AS skills\n" + "ORDER BY score DESC"; Map<String, Object> params = new HashMap<String, Object>(); params.put( "name", name ); return executionEngine.execute( cypher, params ).iterator();}
![Page 56: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/56.jpg)
Cypher Query
public Iterator<Map<String, Object>> findColleaguesFor( String name ) { String cypher = "MATCH (me:Person)-[:WORKS_FOR]->(company),\n" + " (me)-[:HAS_SKILL]->(skill),\n" + " (colleague)-[:WORKS_FOR]->(company),\n" + " (colleague)-[:HAS_SKILL]->(skill)\n" + "WHERE me.name = {name}\n" + "RETURN colleague.name AS name,\n" + " count(skill) AS score,\n" + " collect(skill.name) AS skills\n" + "ORDER BY score DESC"; Map<String, Object> params = new HashMap<String, Object>(); params.put( "name", name ); return executionEngine.execute( cypher, params ).iterator();}
![Page 57: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/57.jpg)
Parameterized Query
public Iterator<Map<String, Object>> findColleaguesFor( String name ) { String cypher = "MATCH (me:Person)-[:WORKS_FOR]->(company),\n" + " (me)-[:HAS_SKILL]->(skill),\n" + " (colleague)-[:WORKS_FOR]->(company),\n" + " (colleague)-[:HAS_SKILL]->(skill)\n" + "WHERE me.name = {name}\n" + "RETURN colleague.name AS name,\n" + " count(skill) AS score,\n" + " collect(skill.name) AS skills\n" + "ORDER BY score DESC"; Map<String, Object> params = new HashMap<String, Object>(); params.put( "name", name ); return executionEngine.execute( cypher, params ).iterator();}
![Page 58: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/58.jpg)
Execute Query
public Iterator<Map<String, Object>> findColleaguesFor( String name ) { String cypher = "MATCH (me:Person)-[:WORKS_FOR]->(company),\n" + " (me)-[:HAS_SKILL]->(skill),\n" + " (colleague)-[:WORKS_FOR]->(company),\n" + " (colleague)-[:HAS_SKILL]->(skill)\n" + "WHERE me.name = {name}\n" + "RETURN colleague.name AS name,\n" + " count(skill) AS score,\n" + " collect(skill.name) AS skills\n" + "ORDER BY score DESC"; Map<String, Object> params = new HashMap<String, Object>(); params.put( "name", name ); return executionEngine.execute( cypher, params ).iterator();}
![Page 59: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/59.jpg)
Server Extension Example
• Same data mode and query as before • This @me, we’ll host ColleagueFinder in a server extension
![Page 60: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/60.jpg)
Server Extension
@Path("/similar-skills")public class ColleagueFinderExtension { private static final ObjectMapper MAPPER = new ObjectMapper(); private final ColleagueFinder colleagueFinder; public ColleagueFinderExtension( @Context CypherExecutor cypherExecutor ) { this.colleagueFinder = new ColleagueFinder( cypherExecutor.getExecutionEngine() ); } @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{name}") public Response getColleagues( @PathParam("name") String name ) throws IOException { String json = MAPPER .writeValueAsString( colleagueFinder.findColleaguesFor( name ) ); return Response.ok().entity( json ).build(); }}
![Page 61: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/61.jpg)
JAX-‐RS Annota@ons
@Path("/similar-skills")public class ColleagueFinderExtension { private static final ObjectMapper MAPPER = new ObjectMapper(); private final ColleagueFinder colleagueFinder; public ColleagueFinderExtension( @Context CypherExecutor cypherExecutor ) { this.colleagueFinder = new ColleagueFinder( cypherExecutor.getExecutionEngine() ); } @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{name}") public Response getColleagues( @PathParam("name") String name ) throws IOException { String json = MAPPER .writeValueAsString( colleagueFinder.findColleaguesFor( name ) ); return Response.ok().entity( json ).build(); }}
![Page 62: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/62.jpg)
Map HTTP Request to Object + Method
@Path("/similar-skills")public class ColleagueFinderExtension { private static final ObjectMapper MAPPER = new ObjectMapper(); private final ColleagueFinder colleagueFinder; public ColleagueFinderExtension( @Context CypherExecutor cypherExecutor ) { this.colleagueFinder = new ColleagueFinder( cypherExecutor.getExecutionEngine() ); } @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{name}") public Response getColleagues( @PathParam("name") String name ) throws IOException { String json = MAPPER .writeValueAsString( colleagueFinder.findColleaguesFor( name ) ); return Response.ok().entity( json ).build(); }}
GET /similar-‐skills /Ian
![Page 63: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/63.jpg)
CypherExecutor Injected by Server
@Path("/similar-skills")public class ColleagueFinderExtension { private static final ObjectMapper MAPPER = new ObjectMapper(); private final ColleagueFinder colleagueFinder; public ColleagueFinderExtension( @Context CypherExecutor cypherExecutor ) { this.colleagueFinder = new ColleagueFinder( cypherExecutor.getExecutionEngine() ); } @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{name}") public Response getColleagues( @PathParam("name") String name ) throws IOException { String json = MAPPER .writeValueAsString( colleagueFinder.findColleaguesFor( name ) ); return Response.ok().entity( json ).build(); }}
Ensures Execu@onEngine reused across resource instances
![Page 64: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/64.jpg)
Generate and Format Response
@Path("/similar-skills")public class ColleagueFinderExtension { private static final ObjectMapper MAPPER = new ObjectMapper(); private final ColleagueFinder colleagueFinder; public ColleagueFinderExtension( @Context CypherExecutor cypherExecutor ) { this.colleagueFinder = new ColleagueFinder( cypherExecutor.getExecutionEngine() ); } @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{name}") public Response getColleagues( @PathParam("name") String name ) throws IOException { String json = MAPPER .writeValueAsString( colleagueFinder.findColleaguesFor( name ) ); return Response.ok().entity( json ).build(); }}
![Page 65: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/65.jpg)
Extension Test Fixture public class ColleagueFinderExtensionTest { private CommunityNeoServer server; @Before public void startServer() throws IOException { server = CommunityServerBuilder.server() .withThirdPartyJaxRsPackage( "org.neo4j.good_practices", "/colleagues" ) .build(); server.start(); ExampleGraph.populate( server.getDatabase().getGraph() ); } @After public void stopServer() { server.stop(); }}
![Page 66: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/66.jpg)
Build and Configure Server public class ColleagueFinderExtensionTest { private CommunityNeoServer server; @Before public void startServer() throws IOException { server = CommunityServerBuilder.server() .withThirdPartyJaxRsPackage( "org.neo4j.good_practices", "/colleagues" ) .build(); server.start(); ExampleGraph.populate( server.getDatabase().getGraph() ); } @After public void stopServer() { server.stop(); }}
![Page 67: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/67.jpg)
Start Server public class ColleagueFinderExtensionTest { private CommunityNeoServer server; @Before public void startServer() throws IOException { server = CommunityServerBuilder.server() .withThirdPartyJaxRsPackage( "org.neo4j.good_practices", "/colleagues" ) .build(); server.start(); ExampleGraph.populate( server.getDatabase().getGraph() ); } @After public void stopServer() { server.stop(); }}
![Page 68: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/68.jpg)
Populate Database public class ColleagueFinderExtensionTest { private CommunityNeoServer server; @Before public void startServer() throws IOException { server = CommunityServerBuilder.server() .withThirdPartyJaxRsPackage( "org.neo4j.good_practices", "/colleagues" ) .build(); server.start(); ExampleGraph.populate( server.getDatabase().getGraph() ); } @After public void stopServer() { server.stop(); }}
![Page 69: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/69.jpg)
CommunityServerBuilder
• Programma@c configura@on <dependency> <groupId>org.neo4j.app</groupId> <artifactId>neo4j-server</artifactId> <version>${project.version}</version> <type>test-jar</type> </dependency>
![Page 70: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/70.jpg)
Tes@ng Extension Using HTTP Client @Testpublic void shouldReturnColleaguesWithSimilarSkills() throws Exception { Client client = Client.create( new DefaultClientConfig() ); WebResource resource = client .resource( "http://localhost:7474/colleagues/similar-skills/Ian" ); ClientResponse response = resource .accept( MediaType.APPLICATION_JSON ) .get( ClientResponse.class ); List<Map<String, Object>> results = new ObjectMapper() .readValue(response.getEntity( String.class ), List.class ); // Assertions ...
![Page 71: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/71.jpg)
Create HTTP Client @Testpublic void shouldReturnColleaguesWithSimilarSkills() throws Exception { Client client = Client.create( new DefaultClientConfig() ); WebResource resource = client .resource( "http://localhost:7474/colleagues/similar-skills/Ian" ); ClientResponse response = resource .accept( MediaType.APPLICATION_JSON ) .get( ClientResponse.class ); List<Map<String, Object>> results = new ObjectMapper() .readValue(response.getEntity( String.class ), List.class ); // Assertions ...
![Page 72: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/72.jpg)
Issue Request @Testpublic void shouldReturnColleaguesWithSimilarSkills() throws Exception { Client client = Client.create( new DefaultClientConfig() ); WebResource resource = client .resource( "http://localhost:7474/colleagues/similar-skills/Ian" ); ClientResponse response = resource .accept( MediaType.APPLICATION_JSON ) .get( ClientResponse.class ); List<Map<String, Object>> results = new ObjectMapper() .readValue(response.getEntity( String.class ), List.class ); // Assertions ...
![Page 73: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/73.jpg)
Parse Response @Testpublic void shouldReturnColleaguesWithSimilarSkills() throws Exception { Client client = Client.create( new DefaultClientConfig() ); WebResource resource = client .resource( "http://localhost:7474/colleagues/similar-skills/Ian" ); ClientResponse response = resource .accept( MediaType.APPLICATION_JSON ) .get( ClientResponse.class ); List<Map<String, Object>> results = new ObjectMapper() .readValue(response.getEntity( String.class ), List.class ); // Assertions ...
![Page 74: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/74.jpg)
Assert Results ... assertEquals( 200, response.getStatus() ); assertEquals( MediaType.APPLICATION_JSON, response.getHeaders().get( "Content-Type" ).get( 0 ) ); assertEquals( "Lucy", results.get( 0 ).get( "name" ) ); assertThat( (Iterable<String>) results.get( 0 ).get( "skills" ), hasItems( "Java", "Neo4j" ) );}
![Page 75: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)](https://reader033.vdocuments.mx/reader033/viewer/2022042714/5551265db4c905f1528b4875/html5/thumbnails/75.jpg)
Thank you Twi$er: @ianSrobinson
#neo4j
Neo4j User Group 30th Oct
Skillsma$er
Ian Robinson, Jim Webber & Emil Eifrem
Graph Databases
h
Compliments
of Neo Technology
github.com/iansrobinson/neo4j-‐good-‐prac@ces