75
Twi$er: @ianSrobinson #neo4j Designing and Building a Graph Database Applica5on

Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)

Embed Size (px)

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.

Citation preview

Page 1: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)

Twi$er:  @ianSrobinson  #neo4j  

Designing  and  Building  a  Graph  Database  Applica5on  

Page 2: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)

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)

complexity = f(size, semi-structure, connectedness)

Data  Complexity  

Page 4: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)

Social  Network  

Page 5: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)

Network  Impact  Analysis  

Page 6: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)

Route  Finding  

Page 7: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)

Recommenda@ons  

Page 8: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)

Logis@cs  

Page 9: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)

Access  Control  

Page 10: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)

Fraud  Analysis  

Page 11: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)

Securi@es  and  Debt  

Image:  orgnet.com  

Page 12: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)

Graphs  Are  Everywhere  

Page 13: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)

Graph  Databases  

•  Store  •  Manage  •  Query   data  

Page 14: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)

Neo4j  is  a  Graph  Database  

Page 15: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)

Labeled  Property  Graph  

Page 16: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)

Designing  a  Graph  Model  

Page 17: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)

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)

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)

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)

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)

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)

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)

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)

Candidate  Data  Model  

(:Company)<-[:WORKS_FOR]-(:Person)-[:HAS_SKILL]->(:Skill)

Page 25: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)

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)

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)

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)

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)

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)

First  Match  

Page 31: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)

Second  Match  

Page 32: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)

Third  Match  

Page 33: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)

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)

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)

Tes@ng  

Page 36: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)

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)

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)

Applica@on  Architectures  

•  Embedded  •  Server  •  Server  with  Extensions  

Page 39: Designing and Building a Graph Database Application - Ian Robinson (Neo Technology)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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