SlideShare una empresa de Scribd logo
1 de 64
Descargar para leer sin conexión
Designing	
  and	
  Building	
  a	
  Graph	
  
Database	
  Applica5on

	
  

Twi9er:	
  @ianSrobinson	
  
#neo4j	
  
	
  
Outline	
  
•  Data	
  modeling	
  with	
  graphs	
  
•  Neo4j	
  applica5on	
  architecture	
  op5ons	
  
•  Tes5ng	
  your	
  data	
  model	
  	
  
Graph	
  data	
  modeling	
  
Labeled	
  Property	
  Graph	
  
Models	
  
Purposeful	
  abstrac5on	
  of	
  a	
  domain	
  designed	
  to	
  
sa5sfy	
  par5cular	
  applica5on/end-­‐user	
  goals	
  

Images:	
  en.wikipedia.org	
  
Example	
  Applica5on	
  
•  Knowledge	
  management	
  
–  People,	
  companies,	
  skills	
  
–  Cross	
  organiza5onal	
  

•  Find	
  my	
  professional	
  social	
  network	
  
–  Exchange	
  knowledge	
  
–  Interest	
  groups	
  
–  Help	
  
–  Staff	
  projects	
  
Applica5on/End-­‐User	
  Goals	
  
As	
  an	
  emp

	
  

loyee	
  

I	
  want	
  to	
  k
now	
  who	
  i
n	
  the	
  comp
has	
  similar
any	
  
	
  skills	
  to	
  m
	
  
e	
  
So	
  that	
  we
	
  can	
  excha
nge	
  knowl
edge	
  
Ques5ons	
  To	
  Ask	
  of	
  the	
  Domain	
  
As	
  an	
  emp
loyee	
  
	
  
I	
  want	
  to	
  k
now	
  who	
  i
n	
  the	
  co
has	
  similar	
  
skills	
  to	
  me mpany	
  
	
  
	
  
So	
  that	
  we
	
  can	
  excha
nge	
  knowle
dge	
  

Which	
  people,	
  who	
  work	
  for	
  the	
  same	
  company	
  
as	
  me,	
  have	
  similar	
  skills	
  to	
  me?	
  
Iden5fy	
  En55es	
  
Which	
  people,	
  who	
  work	
  for	
  the	
  same	
  company	
  
as	
  me,	
  have	
  similar	
  skills	
  to	
  me?	
  
	
  
Person	
  
Company	
  
Skill	
  
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	
  
Convert	
  to	
  Cypher	
  Paths	
  
Rela5onship	
  

Person	
  WORKS_FOR	
  Company	
  
Person	
  HAS_SKILL	
  Skill	
  
Label	
  

(:Person)-[:WORKS_FOR]->(:Company),	
(:Person)-[:HAS_SKILL]->(:Skill)
Consolidate	
  Paths	
  
(:Person)-[:WORKS_FOR]->(:Company),	
(:Person)-[:HAS_SKILL]->(:Skill)	

(:Company)<-[:WORKS_FOR]-(:Person)-[:HAS_SKILL]->(:Skill)
Candidate	
  Data	
  Model	
  
(:Company)<-[:WORKS_FOR]-(:Person)-[:HAS_SKILL]->(:Skill)
Express	
  Ques5on	
  as	
  Graph	
  Pa9ern	
  
Which	
  people,	
  who	
  work	
  for	
  the	
  same	
  company	
  
as	
  me,	
  have	
  similar	
  skills	
  to	
  me?	
  
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 skills	
ORDER BY score DESC
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 skills	
ORDER BY score DESC
Anchor	
  Pa9ern	
  in	
  Graph	
  
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 skills	
ORDER BY score DESC	

Search	
  nodes	
  labeled	
  
‘Person’,	
  matching	
  on	
  
‘name’	
  property	
  
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 skills	
ORDER BY score DESC
First	
  Match	
  
Second	
  Match	
  
Third	
  Match	
  
Running	
  the	
  Query	
  
+-----------------------------------+	
| name
| score | skills
|	
+-----------------------------------+	
| "Lucy" | 2
| ["Java","Neo4j"] |	
| "Bill" | 1
| ["Neo4j"]
|	
+-----------------------------------+	
2 rows
From	
  User	
  Story	
  to	
  Model	
  and	
  Query	
  
As	
  an	
  emp
loyee	
  
	
  
I	
  want	
  to	
  k
now	
  who	
  i
n	
  the	
  co
has	
  similar	
  
skills	
  to	
  me mpany	
  
	
  
	
  
So	
  that	
  we
	
  can	
  excha
nge	
  knowle
dge	
  

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 skills	
ORDER BY score DESC	

?

Which	
  people,	
  who	
  work	
  for	
  the	
  same	
  
company	
  as	
  me,	
  have	
  similar	
  skills	
  to	
  me?	

Person	
  WORKS_FOR	
  Company	
  
Person	
  HAS_SKILL	
  Skill	

(:Company)<-[:WORKS_FOR]-(:Person)-[:HAS_SKILL]->(:Skill)
Tes5ng	
  
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	
  
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…	
  
Applica5on	
  Architectures	
  
•  Embedded	
  
•  Server	
  
•  Server	
  with	
  Extensions	
  
Applica5on	
  Architectures	
  
•  Embedded	
  
–  Host	
  in	
  Java	
  process	
  
–  Access	
  to	
  Java	
  APIs	
  

•  Server	
  
•  Server	
  with	
  Extensions	
  

Applica5on	
  
Java	
  APIs	
  
Applica5on	
  Architectures	
  
•  Embedded	
  
•  Server	
  
–  HTTP/JSON	
  interface	
  
–  Server	
  wraps	
  embedded	
  
instance	
  

•  Server	
  with	
  Extensions	
  

Applica5on	
  
REST	
  Client	
  

Write	
  LB	
  
REST	
  API	
  

REST	
  API	
  

Read	
  LB	
  
REST	
  API	
  
Applica5on	
  Architectures	
  
•  Embedded	
  
•  Server	
  
•  Server	
  with	
  Extensions	
  

REST	
  API	
  

–  Execute	
  complex	
  logic	
  on	
  server	
  
–  Control	
  HTTP	
  request/response	
  format	
  

Extensions	
  
Embedded	
  Example	
  
•  Company	
  social	
  network	
  
•  Find	
  colleagues	
  with	
  similar	
  skills	
  
•  Encapsulate	
  query	
  in	
  a	
  ColleagueFinder
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();	
}	
}
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();	
}	
}
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();	
}	
}
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	
  
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>
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 );	
}
Unit	
  Test	
  
@Test	
public 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() );	
}
Execute	
  Object	
  Under	
  Test	
  
@Test	
public 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() );	
}
Assert	
  Results	
  
@Test	
public 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() );	
}
Ensure	
  No	
  More	
  Results	
  
@Test	
public 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() );	
}
ColleagueFinder	
  
public class ColleagueFinder {	
	
private final ExecutionEngine executionEngine;	
	
public ColleagueFinder( ExecutionEngine executionEngine ) {	
this.executionEngine = executionEngine;	
}	
	
public Iterator<Map<String, Object>> findColleaguesFor( String name ) {	
...	
}	
}
Inject	
  Execu5onEngine	
  
public class ColleagueFinder {	
	
private final ExecutionEngine executionEngine;	
	
public ColleagueFinder( ExecutionEngine executionEngine ) {	
this.executionEngine = executionEngine;	
}	
	
public Iterator<Map<String, Object>> findColleaguesFor( String name ) {	
...	
}	
}
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 skillsn" +	
"ORDER BY score DESC";	
	
Map<String, Object> params = new HashMap<String, Object>();	
params.put( "name", name );	
	
return executionEngine.execute( cypher, params ).iterator();	
}
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 skillsn" +	
"ORDER BY score DESC";	
	
Map<String, Object> params = new HashMap<String, Object>();	
params.put( "name", name );	
	
return executionEngine.execute( cypher, params ).iterator();	
}
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 skillsn" +	
"ORDER BY score DESC";	
	
Map<String, Object> params = new HashMap<String, Object>();	
params.put( "name", name );	
	
return executionEngine.execute( cypher, params ).iterator();	
}
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 skillsn" +	
"ORDER BY score DESC";	
	
Map<String, Object> params = new HashMap<String, Object>();	
params.put( "name", name );	
	
return executionEngine.execute( cypher, params ).iterator();	
}
Server	
  Extension	
  Example	
  
•  Same	
  data	
  mode	
  and	
  query	
  as	
  before	
  
•  This	
  5me,	
  we’ll	
  host	
  ColleagueFinder	
  in	
  a	
  
server	
  extension	
  
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();	
}	
}
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();	
}	
}
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	
  
CypherExecutor	
  Injected	
  by	
  Server	
  
Ensures	
  
Execu5onEngine	
  
reused	
  across	
  
resource	
  instances	
  

@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();	
}	
}
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();	
}	
}
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();	
}	
}
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();	
}	
}
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();	
}	
}
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();	
}	
}
CommunityServerBuilder	
  
•  Programma5c	
  configura5on	
  
	
	
<dependency>	
<groupId>org.neo4j.app</groupId>	
<artifactId>neo4j-server</artifactId>	
<version>${project.version}</version>	
<type>test-jar</type>	
</dependency>
Tes5ng	
  Extension	
  Using	
  HTTP	
  Client	
  
@Test	
public 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	
	
...
Create	
  HTTP	
  Client	
  
@Test	
public 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	
	
...
Issue	
  Request	
  
@Test	
public 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	
	
...
Parse	
  Response	
  
@Test	
public 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	
	
...
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" ) );	
}
ts gy
en lo
i m no
pl h
m ec
Co eo T
N
of

Graph
h
Databases

Thank	
  you	
  
Twi9er:	
  @ianSrobinson	
  
#neo4j	
  
	
  
	
  
	
  

Ian Robinson,
Jim Webber & Emil Eifrem

github.com/iansrobinson/neo4j-­‐good-­‐prac5ces	
  
	
  

Más contenido relacionado

La actualidad más candente

Introducing Neo4j
Introducing Neo4jIntroducing Neo4j
Introducing Neo4jNeo4j
 
Tableau Architecture
Tableau ArchitectureTableau Architecture
Tableau ArchitectureVivek Mohan
 
UNYOUG - APEX 19.2 New Features
UNYOUG - APEX 19.2 New FeaturesUNYOUG - APEX 19.2 New Features
UNYOUG - APEX 19.2 New Featuresmsewtz
 
Webinar: Working with Graph Data in MongoDB
Webinar: Working with Graph Data in MongoDBWebinar: Working with Graph Data in MongoDB
Webinar: Working with Graph Data in MongoDBMongoDB
 
How Graph Databases efficiently store, manage and query connected data at s...
How Graph Databases efficiently  store, manage and query  connected data at s...How Graph Databases efficiently  store, manage and query  connected data at s...
How Graph Databases efficiently store, manage and query connected data at s...jexp
 
Databricks + Snowflake: Catalyzing Data and AI Initiatives
Databricks + Snowflake: Catalyzing Data and AI InitiativesDatabricks + Snowflake: Catalyzing Data and AI Initiatives
Databricks + Snowflake: Catalyzing Data and AI InitiativesDatabricks
 
Graph database Use Cases
Graph database Use CasesGraph database Use Cases
Graph database Use CasesMax De Marzi
 
An Overview of the AWS Cloud Adoption Framework - May 2017 AWS Online Tech Talks
An Overview of the AWS Cloud Adoption Framework - May 2017 AWS Online Tech TalksAn Overview of the AWS Cloud Adoption Framework - May 2017 AWS Online Tech Talks
An Overview of the AWS Cloud Adoption Framework - May 2017 AWS Online Tech TalksAmazon Web Services
 
Streaming data analytics (Kinesis, EMR/Spark) - Pop-up Loft Tel Aviv
Streaming data analytics (Kinesis, EMR/Spark) - Pop-up Loft Tel Aviv Streaming data analytics (Kinesis, EMR/Spark) - Pop-up Loft Tel Aviv
Streaming data analytics (Kinesis, EMR/Spark) - Pop-up Loft Tel Aviv Amazon Web Services
 
MindsDB - Machine Learning in ClickHouse - SF ClickHouse Meetup September 2020
MindsDB - Machine Learning in ClickHouse - SF ClickHouse Meetup September 2020MindsDB - Machine Learning in ClickHouse - SF ClickHouse Meetup September 2020
MindsDB - Machine Learning in ClickHouse - SF ClickHouse Meetup September 2020Altinity Ltd
 
Building social network with Neo4j and Python
Building social network with Neo4j and PythonBuilding social network with Neo4j and Python
Building social network with Neo4j and PythonAndrii Soldatenko
 
Overview of new features in Apache Ranger
Overview of new features in Apache RangerOverview of new features in Apache Ranger
Overview of new features in Apache RangerDataWorks Summit
 
Introduction to Neo4j for the Emirates & Bahrain
Introduction to Neo4j for the Emirates & BahrainIntroduction to Neo4j for the Emirates & Bahrain
Introduction to Neo4j for the Emirates & BahrainNeo4j
 
Streaming using Kafka Flink & Elasticsearch
Streaming using Kafka Flink & ElasticsearchStreaming using Kafka Flink & Elasticsearch
Streaming using Kafka Flink & ElasticsearchKeira Zhou
 
Data Platform Architecture Principles and Evaluation Criteria
Data Platform Architecture Principles and Evaluation CriteriaData Platform Architecture Principles and Evaluation Criteria
Data Platform Architecture Principles and Evaluation CriteriaScyllaDB
 
Data Lake Overview
Data Lake OverviewData Lake Overview
Data Lake OverviewJames Serra
 
iPaaS: A platform for Integration technology convergence
iPaaS: A platform for Integration technology convergenceiPaaS: A platform for Integration technology convergence
iPaaS: A platform for Integration technology convergenceRaveendra Babu Darsi
 
Neo4j 4.1 overview
Neo4j 4.1 overviewNeo4j 4.1 overview
Neo4j 4.1 overviewNeo4j
 

La actualidad más candente (20)

Introducing Neo4j
Introducing Neo4jIntroducing Neo4j
Introducing Neo4j
 
Tableau Architecture
Tableau ArchitectureTableau Architecture
Tableau Architecture
 
UNYOUG - APEX 19.2 New Features
UNYOUG - APEX 19.2 New FeaturesUNYOUG - APEX 19.2 New Features
UNYOUG - APEX 19.2 New Features
 
Webinar: Working with Graph Data in MongoDB
Webinar: Working with Graph Data in MongoDBWebinar: Working with Graph Data in MongoDB
Webinar: Working with Graph Data in MongoDB
 
How Graph Databases efficiently store, manage and query connected data at s...
How Graph Databases efficiently  store, manage and query  connected data at s...How Graph Databases efficiently  store, manage and query  connected data at s...
How Graph Databases efficiently store, manage and query connected data at s...
 
Graph databases
Graph databasesGraph databases
Graph databases
 
HyperGraphQL
HyperGraphQLHyperGraphQL
HyperGraphQL
 
Databricks + Snowflake: Catalyzing Data and AI Initiatives
Databricks + Snowflake: Catalyzing Data and AI InitiativesDatabricks + Snowflake: Catalyzing Data and AI Initiatives
Databricks + Snowflake: Catalyzing Data and AI Initiatives
 
Graph database Use Cases
Graph database Use CasesGraph database Use Cases
Graph database Use Cases
 
An Overview of the AWS Cloud Adoption Framework - May 2017 AWS Online Tech Talks
An Overview of the AWS Cloud Adoption Framework - May 2017 AWS Online Tech TalksAn Overview of the AWS Cloud Adoption Framework - May 2017 AWS Online Tech Talks
An Overview of the AWS Cloud Adoption Framework - May 2017 AWS Online Tech Talks
 
Streaming data analytics (Kinesis, EMR/Spark) - Pop-up Loft Tel Aviv
Streaming data analytics (Kinesis, EMR/Spark) - Pop-up Loft Tel Aviv Streaming data analytics (Kinesis, EMR/Spark) - Pop-up Loft Tel Aviv
Streaming data analytics (Kinesis, EMR/Spark) - Pop-up Loft Tel Aviv
 
MindsDB - Machine Learning in ClickHouse - SF ClickHouse Meetup September 2020
MindsDB - Machine Learning in ClickHouse - SF ClickHouse Meetup September 2020MindsDB - Machine Learning in ClickHouse - SF ClickHouse Meetup September 2020
MindsDB - Machine Learning in ClickHouse - SF ClickHouse Meetup September 2020
 
Building social network with Neo4j and Python
Building social network with Neo4j and PythonBuilding social network with Neo4j and Python
Building social network with Neo4j and Python
 
Overview of new features in Apache Ranger
Overview of new features in Apache RangerOverview of new features in Apache Ranger
Overview of new features in Apache Ranger
 
Introduction to Neo4j for the Emirates & Bahrain
Introduction to Neo4j for the Emirates & BahrainIntroduction to Neo4j for the Emirates & Bahrain
Introduction to Neo4j for the Emirates & Bahrain
 
Streaming using Kafka Flink & Elasticsearch
Streaming using Kafka Flink & ElasticsearchStreaming using Kafka Flink & Elasticsearch
Streaming using Kafka Flink & Elasticsearch
 
Data Platform Architecture Principles and Evaluation Criteria
Data Platform Architecture Principles and Evaluation CriteriaData Platform Architecture Principles and Evaluation Criteria
Data Platform Architecture Principles and Evaluation Criteria
 
Data Lake Overview
Data Lake OverviewData Lake Overview
Data Lake Overview
 
iPaaS: A platform for Integration technology convergence
iPaaS: A platform for Integration technology convergenceiPaaS: A platform for Integration technology convergence
iPaaS: A platform for Integration technology convergence
 
Neo4j 4.1 overview
Neo4j 4.1 overviewNeo4j 4.1 overview
Neo4j 4.1 overview
 

Destacado

Semantic Graph Databases: The Evolution of Relational Databases
Semantic Graph Databases: The Evolution of Relational DatabasesSemantic Graph Databases: The Evolution of Relational Databases
Semantic Graph Databases: The Evolution of Relational DatabasesCambridge Semantics
 
Relational to Graph - Import
Relational to Graph - ImportRelational to Graph - Import
Relational to Graph - ImportNeo4j
 
Graph Database, a little connected tour - Castano
Graph Database, a little connected tour - CastanoGraph Database, a little connected tour - Castano
Graph Database, a little connected tour - CastanoCodemotion
 
Converting Relational to Graph Databases
Converting Relational to Graph DatabasesConverting Relational to Graph Databases
Converting Relational to Graph DatabasesAntonio Maccioni
 
Relational databases vs Non-relational databases
Relational databases vs Non-relational databasesRelational databases vs Non-relational databases
Relational databases vs Non-relational databasesJames Serra
 
Graph Based Recommendation Systems at eBay
Graph Based Recommendation Systems at eBayGraph Based Recommendation Systems at eBay
Graph Based Recommendation Systems at eBayDataStax Academy
 
An Introduction to Graph Databases
An Introduction to Graph DatabasesAn Introduction to Graph Databases
An Introduction to Graph DatabasesInfiniteGraph
 
NoSQL: Why, When, and How
NoSQL: Why, When, and HowNoSQL: Why, When, and How
NoSQL: Why, When, and HowBigBlueHat
 
Neo4j - graph database for recommendations
Neo4j - graph database for recommendationsNeo4j - graph database for recommendations
Neo4j - graph database for recommendationsproksik
 
An Introduction to NOSQL, Graph Databases and Neo4j
An Introduction to NOSQL, Graph Databases and Neo4jAn Introduction to NOSQL, Graph Databases and Neo4j
An Introduction to NOSQL, Graph Databases and Neo4jDebanjan Mahata
 
Introduction to graph databases GraphDays
Introduction to graph databases  GraphDaysIntroduction to graph databases  GraphDays
Introduction to graph databases GraphDaysNeo4j
 
Introduction to Graph Databases
Introduction to Graph DatabasesIntroduction to Graph Databases
Introduction to Graph DatabasesMax De Marzi
 
Data Mining: Graph mining and social network analysis
Data Mining: Graph mining and social network analysisData Mining: Graph mining and social network analysis
Data Mining: Graph mining and social network analysisDataminingTools Inc
 
Data Modeling with Neo4j
Data Modeling with Neo4jData Modeling with Neo4j
Data Modeling with Neo4jNeo4j
 

Destacado (16)

Semantic Graph Databases: The Evolution of Relational Databases
Semantic Graph Databases: The Evolution of Relational DatabasesSemantic Graph Databases: The Evolution of Relational Databases
Semantic Graph Databases: The Evolution of Relational Databases
 
Relational to Graph - Import
Relational to Graph - ImportRelational to Graph - Import
Relational to Graph - Import
 
Graph Database, a little connected tour - Castano
Graph Database, a little connected tour - CastanoGraph Database, a little connected tour - Castano
Graph Database, a little connected tour - Castano
 
Converting Relational to Graph Databases
Converting Relational to Graph DatabasesConverting Relational to Graph Databases
Converting Relational to Graph Databases
 
Relational databases vs Non-relational databases
Relational databases vs Non-relational databasesRelational databases vs Non-relational databases
Relational databases vs Non-relational databases
 
Graph Based Recommendation Systems at eBay
Graph Based Recommendation Systems at eBayGraph Based Recommendation Systems at eBay
Graph Based Recommendation Systems at eBay
 
An Introduction to Graph Databases
An Introduction to Graph DatabasesAn Introduction to Graph Databases
An Introduction to Graph Databases
 
Relational vs. Non-Relational
Relational vs. Non-RelationalRelational vs. Non-Relational
Relational vs. Non-Relational
 
NoSQL: Why, When, and How
NoSQL: Why, When, and HowNoSQL: Why, When, and How
NoSQL: Why, When, and How
 
Lju Lazarevic
Lju LazarevicLju Lazarevic
Lju Lazarevic
 
Neo4j - graph database for recommendations
Neo4j - graph database for recommendationsNeo4j - graph database for recommendations
Neo4j - graph database for recommendations
 
An Introduction to NOSQL, Graph Databases and Neo4j
An Introduction to NOSQL, Graph Databases and Neo4jAn Introduction to NOSQL, Graph Databases and Neo4j
An Introduction to NOSQL, Graph Databases and Neo4j
 
Introduction to graph databases GraphDays
Introduction to graph databases  GraphDaysIntroduction to graph databases  GraphDays
Introduction to graph databases GraphDays
 
Introduction to Graph Databases
Introduction to Graph DatabasesIntroduction to Graph Databases
Introduction to Graph Databases
 
Data Mining: Graph mining and social network analysis
Data Mining: Graph mining and social network analysisData Mining: Graph mining and social network analysis
Data Mining: Graph mining and social network analysis
 
Data Modeling with Neo4j
Data Modeling with Neo4jData Modeling with Neo4j
Data Modeling with Neo4j
 

Similar a Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013

Designing and Building a Graph Database Application - Ian Robinson (Neo Techn...
Designing and Building a Graph Database Application - Ian Robinson (Neo Techn...Designing and Building a Graph Database Application - Ian Robinson (Neo Techn...
Designing and Building a Graph Database Application - Ian Robinson (Neo Techn...jaxLondonConference
 
Data modeling with neo4j tutorial
Data modeling with neo4j tutorialData modeling with neo4j tutorial
Data modeling with neo4j tutorialMax De Marzi
 
20141216 graph database prototyping ams meetup
20141216 graph database prototyping ams meetup20141216 graph database prototyping ams meetup
20141216 graph database prototyping ams meetupRik Van Bruggen
 
The power of polyglot searching
The power of polyglot searchingThe power of polyglot searching
The power of polyglot searchingGraphAware
 
Machine Learning for (JVM) Developers
Machine Learning for (JVM) DevelopersMachine Learning for (JVM) Developers
Machine Learning for (JVM) DevelopersMateusz Dymczyk
 
Alex mang patterns for scalability in microsoft azure application
Alex mang   patterns for scalability in microsoft azure applicationAlex mang   patterns for scalability in microsoft azure application
Alex mang patterns for scalability in microsoft azure applicationCodecamp Romania
 
Leveraging Lucene/Solr as a Knowledge Graph and Intent Engine
Leveraging Lucene/Solr as a Knowledge Graph and Intent EngineLeveraging Lucene/Solr as a Knowledge Graph and Intent Engine
Leveraging Lucene/Solr as a Knowledge Graph and Intent EngineTrey Grainger
 
2018 data warehouse features in spark
2018   data warehouse features in spark2018   data warehouse features in spark
2018 data warehouse features in sparkChester Chen
 
Team Nation 2022 - How to choose between Dataverse, SQL Azure, SharePoint lis...
Team Nation 2022 - How to choose between Dataverse, SQL Azure, SharePoint lis...Team Nation 2022 - How to choose between Dataverse, SQL Azure, SharePoint lis...
Team Nation 2022 - How to choose between Dataverse, SQL Azure, SharePoint lis...serge luca
 
Salesforce Basic Development
Salesforce Basic DevelopmentSalesforce Basic Development
Salesforce Basic DevelopmentNaveen Dhanaraj
 
Net campus2015 antimomusone
Net campus2015 antimomusoneNet campus2015 antimomusone
Net campus2015 antimomusoneDotNetCampus
 
PREDICT THE FUTURE , MACHINE LEARNING & BIG DATA
PREDICT THE FUTURE , MACHINE LEARNING & BIG DATAPREDICT THE FUTURE , MACHINE LEARNING & BIG DATA
PREDICT THE FUTURE , MACHINE LEARNING & BIG DATADotNetCampus
 
Deep-Dive into Deep Learning Pipelines with Sue Ann Hong and Tim Hunter
Deep-Dive into Deep Learning Pipelines with Sue Ann Hong and Tim HunterDeep-Dive into Deep Learning Pipelines with Sue Ann Hong and Tim Hunter
Deep-Dive into Deep Learning Pipelines with Sue Ann Hong and Tim HunterDatabricks
 
Continuous delivery for machine learning
Continuous delivery for machine learningContinuous delivery for machine learning
Continuous delivery for machine learningRajesh Muppalla
 
Building Content Recommendation Systems Using Apache MXNet and Gluon - MCL402...
Building Content Recommendation Systems Using Apache MXNet and Gluon - MCL402...Building Content Recommendation Systems Using Apache MXNet and Gluon - MCL402...
Building Content Recommendation Systems Using Apache MXNet and Gluon - MCL402...Amazon Web Services
 
Planning with Polyalgebra: Bringing Together Relational, Complex and Machine ...
Planning with Polyalgebra: Bringing Together Relational, Complex and Machine ...Planning with Polyalgebra: Bringing Together Relational, Complex and Machine ...
Planning with Polyalgebra: Bringing Together Relational, Complex and Machine ...Julian Hyde
 
Efficient Rails Test Driven Development (class 3) by Wolfram Arnold
Efficient Rails Test Driven Development (class 3) by Wolfram ArnoldEfficient Rails Test Driven Development (class 3) by Wolfram Arnold
Efficient Rails Test Driven Development (class 3) by Wolfram ArnoldMarakana Inc.
 
Lightning-fast Analytics for Workday transactional data
Lightning-fast Analytics for Workday transactional dataLightning-fast Analytics for Workday transactional data
Lightning-fast Analytics for Workday transactional dataPavel Hardak
 

Similar a Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013 (20)

Designing and Building a Graph Database Application - Ian Robinson (Neo Techn...
Designing and Building a Graph Database Application - Ian Robinson (Neo Techn...Designing and Building a Graph Database Application - Ian Robinson (Neo Techn...
Designing and Building a Graph Database Application - Ian Robinson (Neo Techn...
 
Data modeling with neo4j tutorial
Data modeling with neo4j tutorialData modeling with neo4j tutorial
Data modeling with neo4j tutorial
 
20141216 graph database prototyping ams meetup
20141216 graph database prototyping ams meetup20141216 graph database prototyping ams meetup
20141216 graph database prototyping ams meetup
 
The power of polyglot searching
The power of polyglot searchingThe power of polyglot searching
The power of polyglot searching
 
Power of Polyglot Search
Power of Polyglot SearchPower of Polyglot Search
Power of Polyglot Search
 
Machine Learning for (JVM) Developers
Machine Learning for (JVM) DevelopersMachine Learning for (JVM) Developers
Machine Learning for (JVM) Developers
 
Alex mang patterns for scalability in microsoft azure application
Alex mang   patterns for scalability in microsoft azure applicationAlex mang   patterns for scalability in microsoft azure application
Alex mang patterns for scalability in microsoft azure application
 
Leveraging Lucene/Solr as a Knowledge Graph and Intent Engine
Leveraging Lucene/Solr as a Knowledge Graph and Intent EngineLeveraging Lucene/Solr as a Knowledge Graph and Intent Engine
Leveraging Lucene/Solr as a Knowledge Graph and Intent Engine
 
2018 data warehouse features in spark
2018   data warehouse features in spark2018   data warehouse features in spark
2018 data warehouse features in spark
 
Team Nation 2022 - How to choose between Dataverse, SQL Azure, SharePoint lis...
Team Nation 2022 - How to choose between Dataverse, SQL Azure, SharePoint lis...Team Nation 2022 - How to choose between Dataverse, SQL Azure, SharePoint lis...
Team Nation 2022 - How to choose between Dataverse, SQL Azure, SharePoint lis...
 
Salesforce Basic Development
Salesforce Basic DevelopmentSalesforce Basic Development
Salesforce Basic Development
 
Net campus2015 antimomusone
Net campus2015 antimomusoneNet campus2015 antimomusone
Net campus2015 antimomusone
 
PREDICT THE FUTURE , MACHINE LEARNING & BIG DATA
PREDICT THE FUTURE , MACHINE LEARNING & BIG DATAPREDICT THE FUTURE , MACHINE LEARNING & BIG DATA
PREDICT THE FUTURE , MACHINE LEARNING & BIG DATA
 
Deep-Dive into Deep Learning Pipelines with Sue Ann Hong and Tim Hunter
Deep-Dive into Deep Learning Pipelines with Sue Ann Hong and Tim HunterDeep-Dive into Deep Learning Pipelines with Sue Ann Hong and Tim Hunter
Deep-Dive into Deep Learning Pipelines with Sue Ann Hong and Tim Hunter
 
Continuous delivery for machine learning
Continuous delivery for machine learningContinuous delivery for machine learning
Continuous delivery for machine learning
 
Building Content Recommendation Systems Using Apache MXNet and Gluon - MCL402...
Building Content Recommendation Systems Using Apache MXNet and Gluon - MCL402...Building Content Recommendation Systems Using Apache MXNet and Gluon - MCL402...
Building Content Recommendation Systems Using Apache MXNet and Gluon - MCL402...
 
Polyalgebra
PolyalgebraPolyalgebra
Polyalgebra
 
Planning with Polyalgebra: Bringing Together Relational, Complex and Machine ...
Planning with Polyalgebra: Bringing Together Relational, Complex and Machine ...Planning with Polyalgebra: Bringing Together Relational, Complex and Machine ...
Planning with Polyalgebra: Bringing Together Relational, Complex and Machine ...
 
Efficient Rails Test Driven Development (class 3) by Wolfram Arnold
Efficient Rails Test Driven Development (class 3) by Wolfram ArnoldEfficient Rails Test Driven Development (class 3) by Wolfram Arnold
Efficient Rails Test Driven Development (class 3) by Wolfram Arnold
 
Lightning-fast Analytics for Workday transactional data
Lightning-fast Analytics for Workday transactional dataLightning-fast Analytics for Workday transactional data
Lightning-fast Analytics for Workday transactional data
 

Más de Neo4j

Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
QIAGEN: Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
QIAGEN: Biomedical Knowledge Graphs for Data Scientists and BioinformaticiansQIAGEN: Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
QIAGEN: Biomedical Knowledge Graphs for Data Scientists and BioinformaticiansNeo4j
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphNeo4j
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Neo4j
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfNeo4j
 
ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...
ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...
ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...Neo4j
 
BBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafos
BBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafosBBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafos
BBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafosNeo4j
 
Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...
Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...
Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...Neo4j
 
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4jGraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4jNeo4j
 
Neo4j_Exploring the Impact of Graph Technology on Financial Services.pdf
Neo4j_Exploring the Impact of Graph Technology on Financial Services.pdfNeo4j_Exploring the Impact of Graph Technology on Financial Services.pdf
Neo4j_Exploring the Impact of Graph Technology on Financial Services.pdfNeo4j
 
Rabobank_Exploring the Impact of Graph Technology on Financial Services.pdf
Rabobank_Exploring the Impact of Graph Technology on Financial Services.pdfRabobank_Exploring the Impact of Graph Technology on Financial Services.pdf
Rabobank_Exploring the Impact of Graph Technology on Financial Services.pdfNeo4j
 
Webinar - IA generativa e grafi Neo4j: RAG time!
Webinar - IA generativa e grafi Neo4j: RAG time!Webinar - IA generativa e grafi Neo4j: RAG time!
Webinar - IA generativa e grafi Neo4j: RAG time!Neo4j
 
IA Generativa y Grafos de Neo4j: RAG time
IA Generativa y Grafos de Neo4j: RAG timeIA Generativa y Grafos de Neo4j: RAG time
IA Generativa y Grafos de Neo4j: RAG timeNeo4j
 
Neo4j: Data Engineering for RAG (retrieval augmented generation)
Neo4j: Data Engineering for RAG (retrieval augmented generation)Neo4j: Data Engineering for RAG (retrieval augmented generation)
Neo4j: Data Engineering for RAG (retrieval augmented generation)Neo4j
 
Neo4j Graph Summit 2024 Workshop - EMEA - Breda_and_Munchen.pdf
Neo4j Graph Summit 2024 Workshop - EMEA - Breda_and_Munchen.pdfNeo4j Graph Summit 2024 Workshop - EMEA - Breda_and_Munchen.pdf
Neo4j Graph Summit 2024 Workshop - EMEA - Breda_and_Munchen.pdfNeo4j
 
Enabling GenAI Breakthroughs with Knowledge Graphs
Enabling GenAI Breakthroughs with Knowledge GraphsEnabling GenAI Breakthroughs with Knowledge Graphs
Enabling GenAI Breakthroughs with Knowledge GraphsNeo4j
 
Neo4j_Anurag Tandon_Product Vision and Roadmap.Benelux.pptx.pdf
Neo4j_Anurag Tandon_Product Vision and Roadmap.Benelux.pptx.pdfNeo4j_Anurag Tandon_Product Vision and Roadmap.Benelux.pptx.pdf
Neo4j_Anurag Tandon_Product Vision and Roadmap.Benelux.pptx.pdfNeo4j
 
Neo4j Jesus Barrasa The Art of the Possible with Graph
Neo4j Jesus Barrasa The Art of the Possible with GraphNeo4j Jesus Barrasa The Art of the Possible with Graph
Neo4j Jesus Barrasa The Art of the Possible with GraphNeo4j
 

Más de Neo4j (20)

Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
QIAGEN: Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
QIAGEN: Biomedical Knowledge Graphs for Data Scientists and BioinformaticiansQIAGEN: Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
QIAGEN: Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdf
 
ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...
ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...
ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...
 
BBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafos
BBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafosBBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafos
BBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafos
 
Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...
Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...
Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...
 
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4jGraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
GraphSummit Madrid - Product Vision and Roadmap - Luis Salvador Neo4j
 
Neo4j_Exploring the Impact of Graph Technology on Financial Services.pdf
Neo4j_Exploring the Impact of Graph Technology on Financial Services.pdfNeo4j_Exploring the Impact of Graph Technology on Financial Services.pdf
Neo4j_Exploring the Impact of Graph Technology on Financial Services.pdf
 
Rabobank_Exploring the Impact of Graph Technology on Financial Services.pdf
Rabobank_Exploring the Impact of Graph Technology on Financial Services.pdfRabobank_Exploring the Impact of Graph Technology on Financial Services.pdf
Rabobank_Exploring the Impact of Graph Technology on Financial Services.pdf
 
Webinar - IA generativa e grafi Neo4j: RAG time!
Webinar - IA generativa e grafi Neo4j: RAG time!Webinar - IA generativa e grafi Neo4j: RAG time!
Webinar - IA generativa e grafi Neo4j: RAG time!
 
IA Generativa y Grafos de Neo4j: RAG time
IA Generativa y Grafos de Neo4j: RAG timeIA Generativa y Grafos de Neo4j: RAG time
IA Generativa y Grafos de Neo4j: RAG time
 
Neo4j: Data Engineering for RAG (retrieval augmented generation)
Neo4j: Data Engineering for RAG (retrieval augmented generation)Neo4j: Data Engineering for RAG (retrieval augmented generation)
Neo4j: Data Engineering for RAG (retrieval augmented generation)
 
Neo4j Graph Summit 2024 Workshop - EMEA - Breda_and_Munchen.pdf
Neo4j Graph Summit 2024 Workshop - EMEA - Breda_and_Munchen.pdfNeo4j Graph Summit 2024 Workshop - EMEA - Breda_and_Munchen.pdf
Neo4j Graph Summit 2024 Workshop - EMEA - Breda_and_Munchen.pdf
 
Enabling GenAI Breakthroughs with Knowledge Graphs
Enabling GenAI Breakthroughs with Knowledge GraphsEnabling GenAI Breakthroughs with Knowledge Graphs
Enabling GenAI Breakthroughs with Knowledge Graphs
 
Neo4j_Anurag Tandon_Product Vision and Roadmap.Benelux.pptx.pdf
Neo4j_Anurag Tandon_Product Vision and Roadmap.Benelux.pptx.pdfNeo4j_Anurag Tandon_Product Vision and Roadmap.Benelux.pptx.pdf
Neo4j_Anurag Tandon_Product Vision and Roadmap.Benelux.pptx.pdf
 
Neo4j Jesus Barrasa The Art of the Possible with Graph
Neo4j Jesus Barrasa The Art of the Possible with GraphNeo4j Jesus Barrasa The Art of the Possible with Graph
Neo4j Jesus Barrasa The Art of the Possible with Graph
 

Último

Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilV3cube
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 

Último (20)

Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 

Designing and Building a Graph Database Application – Architectural Choices, Data Modeling, and Testing - Ian Robinson @ GraphConnect NY 2013

  • 1. Designing  and  Building  a  Graph   Database  Applica5on   Twi9er:  @ianSrobinson   #neo4j    
  • 2. Outline   •  Data  modeling  with  graphs   •  Neo4j  applica5on  architecture  op5ons   •  Tes5ng  your  data  model    
  • 5. Models   Purposeful  abstrac5on  of  a  domain  designed  to   sa5sfy  par5cular  applica5on/end-­‐user  goals   Images:  en.wikipedia.org  
  • 6. Example  Applica5on   •  Knowledge  management   –  People,  companies,  skills   –  Cross  organiza5onal   •  Find  my  professional  social  network   –  Exchange  knowledge   –  Interest  groups   –  Help   –  Staff  projects  
  • 7. Applica5on/End-­‐User  Goals   As  an  emp   loyee   I  want  to  k now  who  i n  the  comp has  similar any    skills  to  m   e   So  that  we  can  excha nge  knowl edge  
  • 8. Ques5ons  To  Ask  of  the  Domain   As  an  emp loyee     I  want  to  k now  who  i n  the  co has  similar   skills  to  me mpany       So  that  we  can  excha nge  knowle dge   Which  people,  who  work  for  the  same  company   as  me,  have  similar  skills  to  me?  
  • 9. Iden5fy  En55es   Which  people,  who  work  for  the  same  company   as  me,  have  similar  skills  to  me?     Person   Company   Skill  
  • 10. 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  
  • 11. Convert  to  Cypher  Paths   Rela5onship   Person  WORKS_FOR  Company   Person  HAS_SKILL  Skill   Label   (:Person)-[:WORKS_FOR]->(:Company), (:Person)-[:HAS_SKILL]->(:Skill)
  • 13. Candidate  Data  Model   (:Company)<-[:WORKS_FOR]-(:Person)-[:HAS_SKILL]->(:Skill)
  • 14. Express  Ques5on  as  Graph  Pa9ern   Which  people,  who  work  for  the  same  company   as  me,  have  similar  skills  to  me?  
  • 15. 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 skills ORDER BY score DESC
  • 16. 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 skills ORDER BY score DESC
  • 17. Anchor  Pa9ern  in  Graph   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 skills ORDER BY score DESC Search  nodes  labeled   ‘Person’,  matching  on   ‘name’  property  
  • 18. 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 skills ORDER BY score DESC
  • 22. Running  the  Query   +-----------------------------------+ | name | score | skills | +-----------------------------------+ | "Lucy" | 2 | ["Java","Neo4j"] | | "Bill" | 1 | ["Neo4j"] | +-----------------------------------+ 2 rows
  • 23. From  User  Story  to  Model  and  Query   As  an  emp loyee     I  want  to  k now  who  i n  the  co has  similar   skills  to  me mpany       So  that  we  can  excha nge  knowle dge   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 skills ORDER BY score DESC ? Which  people,  who  work  for  the  same   company  as  me,  have  similar  skills  to  me? Person  WORKS_FOR  Company   Person  HAS_SKILL  Skill (:Company)<-[:WORKS_FOR]-(:Person)-[:HAS_SKILL]->(:Skill)
  • 25. 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  
  • 26. 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…  
  • 27. Applica5on  Architectures   •  Embedded   •  Server   •  Server  with  Extensions  
  • 28. Applica5on  Architectures   •  Embedded   –  Host  in  Java  process   –  Access  to  Java  APIs   •  Server   •  Server  with  Extensions   Applica5on   Java  APIs  
  • 29. Applica5on  Architectures   •  Embedded   •  Server   –  HTTP/JSON  interface   –  Server  wraps  embedded   instance   •  Server  with  Extensions   Applica5on   REST  Client   Write  LB   REST  API   REST  API   Read  LB   REST  API  
  • 30. Applica5on  Architectures   •  Embedded   •  Server   •  Server  with  Extensions   REST  API   –  Execute  complex  logic  on  server   –  Control  HTTP  request/response  format   Extensions  
  • 31. Embedded  Example   •  Company  social  network   •  Find  colleagues  with  similar  skills   •  Encapsulate  query  in  a  ColleagueFinder
  • 32. 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(); } }
  • 33. 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(); } }
  • 34. 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(); } }
  • 35. 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  
  • 36. 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>
  • 37. 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 ); }
  • 38. Unit  Test   @Test public 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() ); }
  • 39. Execute  Object  Under  Test   @Test public 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() ); }
  • 40. Assert  Results   @Test public 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() ); }
  • 41. Ensure  No  More  Results   @Test public 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() ); }
  • 42. ColleagueFinder   public class ColleagueFinder { private final ExecutionEngine executionEngine; public ColleagueFinder( ExecutionEngine executionEngine ) { this.executionEngine = executionEngine; } public Iterator<Map<String, Object>> findColleaguesFor( String name ) { ... } }
  • 43. Inject  Execu5onEngine   public class ColleagueFinder { private final ExecutionEngine executionEngine; public ColleagueFinder( ExecutionEngine executionEngine ) { this.executionEngine = executionEngine; } public Iterator<Map<String, Object>> findColleaguesFor( String name ) { ... } }
  • 44. 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 skillsn" + "ORDER BY score DESC"; Map<String, Object> params = new HashMap<String, Object>(); params.put( "name", name ); return executionEngine.execute( cypher, params ).iterator(); }
  • 45. 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 skillsn" + "ORDER BY score DESC"; Map<String, Object> params = new HashMap<String, Object>(); params.put( "name", name ); return executionEngine.execute( cypher, params ).iterator(); }
  • 46. 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 skillsn" + "ORDER BY score DESC"; Map<String, Object> params = new HashMap<String, Object>(); params.put( "name", name ); return executionEngine.execute( cypher, params ).iterator(); }
  • 47. 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 skillsn" + "ORDER BY score DESC"; Map<String, Object> params = new HashMap<String, Object>(); params.put( "name", name ); return executionEngine.execute( cypher, params ).iterator(); }
  • 48. Server  Extension  Example   •  Same  data  mode  and  query  as  before   •  This  5me,  we’ll  host  ColleagueFinder  in  a   server  extension  
  • 49. 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(); } }
  • 50. 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(); } }
  • 51. 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  
  • 52. CypherExecutor  Injected  by  Server   Ensures   Execu5onEngine   reused  across   resource  instances   @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(); } }
  • 53. 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(); } }
  • 54. 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(); } }
  • 55. 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(); } }
  • 56. 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(); } }
  • 57. 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(); } }
  • 58. CommunityServerBuilder   •  Programma5c  configura5on   <dependency> <groupId>org.neo4j.app</groupId> <artifactId>neo4j-server</artifactId> <version>${project.version}</version> <type>test-jar</type> </dependency>
  • 59. Tes5ng  Extension  Using  HTTP  Client   @Test public 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 ...
  • 60. Create  HTTP  Client   @Test public 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 ...
  • 61. Issue  Request   @Test public 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 ...
  • 62. Parse  Response   @Test public 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 ...
  • 63. 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" ) ); }
  • 64. ts gy en lo i m no pl h m ec Co eo T N of Graph h Databases Thank  you   Twi9er:  @ianSrobinson   #neo4j         Ian Robinson, Jim Webber & Emil Eifrem github.com/iansrobinson/neo4j-­‐good-­‐prac5ces