designing and building a graph database application – architectural choices, data modeling, and...
DESCRIPTION
Ian closely looks at design and implementation strategies you can employ when building a Neo4j-based graph database solution, including architectural choices, data modelling, and testing.gTRANSCRIPT
![Page 1: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/1.jpg)
Designing and Building a Graph Database Applica5on
Twi9er: @ianSrobinson #neo4j
![Page 2: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/2.jpg)
Outline
• Data modeling with graphs • Neo4j applica5on architecture op5ons • Tes5ng your data model
![Page 3: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/3.jpg)
Graph data modeling
![Page 4: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/4.jpg)
Labeled Property Graph
![Page 5: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/5.jpg)
Models
Images: en.wikipedia.org
Purposeful abstrac5on of a domain designed to sa5sfy par5cular applica5on/end-‐user goals
![Page 6: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/6.jpg)
Example Applica5on
• Knowledge management – People, companies, skills – Cross organiza5onal
• Find my professional social network – Exchange knowledge – Interest groups – Help – Staff projects
![Page 7: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/7.jpg)
Applica5on/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 8: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/8.jpg)
Ques5ons 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 9: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/9.jpg)
Iden5fy En55es
Which people, who work for the same company as me, have similar skills to me? Person Company Skill
![Page 10: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/10.jpg)
Iden5fy Rela5onships Between En55es
Which people, who work for the same company as me, have similar skills to me? Person WORKS_FOR Company Person HAS_SKILL Skill
![Page 11: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/11.jpg)
Convert to Cypher Paths
Person WORKS_FOR Company Person HAS_SKILL Skill
Rela5onship
Label
(:Person)-[:WORKS_FOR]->(:Company),(:Person)-[:HAS_SKILL]->(:Skill)
![Page 12: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/12.jpg)
Consolidate Paths
(:Person)-[:WORKS_FOR]->(:Company),(:Person)-[:HAS_SKILL]->(:Skill)
(:Company)<-[:WORKS_FOR]-(:Person)-[:HAS_SKILL]->(:Skill)
![Page 13: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/13.jpg)
Candidate Data Model
(:Company)<-[:WORKS_FOR]-(:Person)-[:HAS_SKILL]->(:Skill)
![Page 14: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/14.jpg)
Express Ques5on as Graph Pa9ern
Which people, who work for the same company as me, have similar skills to me?
![Page 15: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/15.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 16: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/16.jpg)
Graph Pa9ern
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 17: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/17.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 Pa9ern in Graph
Search nodes labeled ‘Person’, matching on
‘name’ property
![Page 18: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/18.jpg)
Create Projec5on 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 19: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/19.jpg)
First Match
![Page 20: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/20.jpg)
Second Match
![Page 21: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/21.jpg)
Third Match
![Page 22: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/22.jpg)
Running the Query
+-----------------------------------+| name | score | skills |+-----------------------------------+| "Lucy" | 2 | ["Java","Neo4j"] || "Bill" | 1 | ["Neo4j"] |+-----------------------------------+2 rows
![Page 23: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/23.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 24: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/24.jpg)
Tes5ng
![Page 25: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/25.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 excep5ons
• Provide a regression test suite – Allows you to change and evolve model and queries
![Page 26: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/26.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 applica5on architecture…
![Page 27: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/27.jpg)
Applica5on Architectures
• Embedded • Server • Server with Extensions
![Page 28: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/28.jpg)
Applica5on Architectures
• Embedded – Host in Java process – Access to Java APIs
• Server • Server with Extensions
Java APIs
Applica5on
![Page 29: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/29.jpg)
Applica5on Architectures
• Embedded • Server – HTTP/JSON interface – Server wraps embedded instance
• Server with Extensions
REST API REST API REST API
REST Client
Applica5on
Write LB Read LB
![Page 30: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/30.jpg)
Applica5on Architectures
• Embedded • Server • Server with Extensions – Execute complex logic on server – Control HTTP request/response format
REST API Extensions
![Page 31: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/31.jpg)
Embedded Example
• Company social network • Find colleagues with similar skills • Encapsulate query in a ColleagueFinder
![Page 32: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/32.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 33: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/33.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 34: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/34.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 35: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/35.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 Execu5onEngine
![Page 36: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/36.jpg)
ImpermanentGraphDatabase
• In-‐memory • For tes5ng only, not produc5on! <dependency> <groupId>org.neo4j</groupId> <artifactId>neo4j-kernel</artifactId> <version>${project.version}</version> <type>test-jar</type> <scope>test</scope> </dependency>
![Page 37: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/37.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 38: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/38.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 39: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/39.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 40: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/40.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 41: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/41.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 42: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/42.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 43: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/43.jpg)
Inject Execu5onEngine
public class ColleagueFinder { private final ExecutionEngine executionEngine; public ColleagueFinder( ExecutionEngine executionEngine ) { this.executionEngine = executionEngine; } public Iterator<Map<String, Object>> findColleaguesFor( String name ) { ... }}
![Page 44: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/44.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 45: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/45.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 46: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/46.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 47: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/47.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 48: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/48.jpg)
Server Extension Example
• Same data mode and query as before • This 5me, we’ll host ColleagueFinder in a server extension
![Page 49: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/49.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 50: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/50.jpg)
JAX-‐RS Annota5ons
@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 51: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/51.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 52: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/52.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 Execu5onEngine reused across resource instances
![Page 53: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/53.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 54: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/54.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 55: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/55.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 56: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/56.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 57: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/57.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 58: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/58.jpg)
CommunityServerBuilder
• Programma5c configura5on <dependency> <groupId>org.neo4j.app</groupId> <artifactId>neo4j-server</artifactId> <version>${project.version}</version> <type>test-jar</type> </dependency>
![Page 59: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/59.jpg)
Tes5ng 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 60: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/60.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 61: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/61.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 62: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/62.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 63: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/63.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 64: Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013](https://reader034.vdocuments.us/reader034/viewer/2022051818/54b6b7b94a79594a538b45d7/html5/thumbnails/64.jpg)
Thank you
Twi9er: @ianSrobinson #neo4j
Ian Robinson, Jim Webber & Emil Eifrem
Graph Databases
h
Compliments
of Neo Technology
github.com/iansrobinson/neo4j-‐good-‐prac5ces