SlideShare a Scribd company logo
1 of 104
Download to read offline
A soft introduction to

(Reality)-[:IS_A]->(Graph)

@fbiville / @LateraIThoughts / florent.biville.net / www.lateral-thoughts.com
What we have always known

selection sort (O(n2))
What we have always known

selection sort (O(n2))
|
heap sort (O(n*log(n))
What we have always known

selection sort (O(n2))
|
heap sort (O(n*log(n))

same algorithm, different data structure,
better execution time !
What we have always known

1 data structure
1 usage
One NOSQL lesson?

1 data STORE
1 usage
One NOSQL lesson?

polyglot persistence, anyone ?
ZOOM on Graph Databases

graph
=
nodes/vertices
+
edges/relationships/arcs
Graph DB : a common model
property graph
=
nodes
+
labeled relationships
+
K/V pairs
Graph DB : a common model
property graph
=
labeledneov2 nodes
+
labeled relationships
+
K/V pairs
Property Graph DBs

lock DB
F
Property Graph DBs

WHY DO THEY

KICK ASS?
BECAUSE
Graph-based computing

Intuitive model
Expressive querying
Powerful analyses
Graph-based computing

Intuitive model

Whiteboard-friendliness

Expressive querying

Pregel (GOOG), TAO (FB)

Powerful analyses

Pattern matching, path
finding...
A glimpse at usecases: mantra

RELATIONSHIPS
ARE AS IMPORTANT AS

E N T I T I E S
A glimpse at usecases
Recommendations
People I may know

ex: people known by contacts I have
worked with in the past
A glimpse at usecases
Recommendations
People I may know

ex: people known by contacts I have
worked with in the past

Products I should buy

ex: people who bought “Twilight” and
“Justin Bieber biography” like you
also bought “The ultimate emo
guide”
A glimpse at usecases
Recommendations
People I may know

ex: people known by contacts I have
worked with in the past

Products I should buy

ex: people who bought “Twilight” and
“Justin Bieber biography” like you
also bought “The ultimate emo
guide”

Movies I should watch with whom and where...
A glimpse at usecases
Pattern detection
Fraud

ex: many IPs from Fraudistan have
made a purchase of game X
in the last hour
A glimpse at usecases
Pattern detection
Fraud

ex: many IPs from Fraudistan have
made a purchase of game X
in the last hour

Disease detection

ex: DNA sequencing
A glimpse at usecases
Pattern detection
Fraud

ex: many IPs from Fraudistan have
made a purchase of game X
in the last hour

Disease detection

ex: DNA sequencing

Trend detection

ex: the term Flu has been tweeted
789% times more in Guatemala area
in the last 24 hours
A glimpse at usecases
Path finding
Genealogy

ex: is François Mitterand related to
Elizabeth II ? (yes)
A glimpse at usecases
Path finding
Genealogy

ex: is François Mitterand related to
Elizabeth II ? (yes)

Navigation

ex: what is the cheapest way to go
to a sushi < 15€ for me (Place de
Clichy) and my friend (Place d’Italie)?
A glimpse at usecases
Path finding
Genealogy

ex: is François Mitterand related to
Elizabeth II ? (yes)

Navigation

ex: what is the cheapest way to go
to a sushi < 15€ for me (Place de
Clichy) and my friend (Place d’Italie)?

Impact analysis

ex: which customers are impacted if
network switch XYZ fails?
A glimpse at usecases
and more...
Topological ordering

ex: given a set of dependencies, in
which order should I include them?

Community detection

ex: tag clustering on annotated
resources to detect groups of interest
(targeted advertising)

and much more...
A glimpse at usecases

http://www.opentreeoflife.org/

http://bio4j.com/

http://www.reco4j.org/

https://github.com/neo4j-contrib/graphgist/wiki
In short

GRAPHS ARE

EVERYWHERE!
THAT’S WHY
YOU
SHOULD TRY
Neo4J - the origins

Circa 2000, somewhere in Sweden
2 swedish guys hacking in a garage
Neo4J - the origins
Dialogue
- Man, I cannot stand Informix anymore
- Right, we’ve pushed it to the limit
- All these documents, these workflows…
- Right, it’s way too densely connected.
- Connected… connections? CONNECTIONS??
Flash-forward: Neo Technology!

1 company

Neo Technology

1 main product

Neo4J

~50 employees
All over the world

Sweden, US, Germany,
France, Malaysia, NZ...
Neo4J - moaar facts & figures

Versions

2.0.0.M06 / 1.9.4

Licenses

GPL, AGPL, OEM, Commercial

235 nodes

34_359_738_368

235 relationships
> 236 properties

at most 238

… capacity can be tailored on demand
Neo4J anatomy
GRAPH
ON DISK
(roughly)

original presentation: http://www.ustream.tv/channel/neo4j
CORE
API
Neo4J anatomy
Node CRUD (JVM)

GraphDatabaseService graphDB = new TestGraphDatabaseFactory ()
.newImpermanentDatabase();

try (Transaction transaction = graphDB.beginTx()) {
Node character =graphDB.createNode( DynamicLabel .label("CHARACTER" ));
character.setProperty( "name", "Homer Simpson" );
transaction .success();
}
Node CRUD (JVM)
officially distributed
test version!

GraphDatabaseService graphDB = new TestGraphDatabaseFactory()
.newImpermanentDatabase();

try (Transaction transaction = graphDB.beginTx()) {
Node character =graphDB.createNode( DynamicLabel .label("CHARACTER" ));
character.setProperty( "name", "Homer Simpson" );
transaction .success();
}
Node CRUD (JVM)

GraphDatabaseService graphDB = new TestGraphDatabaseFactory ()
.newImpermanentDatabase();

try (Transaction transaction = graphDB.beginTx()) {
Node character =graphDB.createNode( DynamicLabel .label("CHARACTER" ));
character.setProperty( "name", "Homer Simpson" );
transaction .success();
}

transaction is MANDATORY
Java 7 required since 2.0
Node CRUD (JVM)

GraphDatabaseService graphDB = new TestGraphDatabaseFactory ()
.newImpermanentDatabase();

try (Transaction transaction = graphDB.beginTx()) {
Node character =graphDB.createNode( DynamicLabel.label("CHARACTER"));
character.setProperty( "name", "Homer Simpson" );
transaction .success();
}

labels are a way
to semi-structure your nodes
(since 2.0)
Node CRUD (JVM)

try (Transaction transaction = graphDB.beginTx()) {
for (Node node: graphDB.findNodesByLabelAndProperty(
DynamicLabel .label("CHARACTER" ),
"name",
"Homer Simpson" )) {
/* do something very useful */
}
transaction .success();
}
Node CRUD (JVM)

try (Transaction transaction = graphDB.beginTx()) {
for (Node node: graphDB.findNodesByLabelAndProperty(
DynamicLabel .label("CHARACTER" ),
"name",
"Homer Simpson" )) {
/* do something very useful */
}
transaction .success();
}

Gotchas
●

avoid graphDB.findById !!!

●

transaction is MANDATORY for reads as well (new in 2.0)
Node CRUD (JVM)

try (Transaction transaction = graphDB.beginTx()) {
Node character = /*lookup*/ ;
character.delete();
transaction .success();
}
Node CRUD (JVM)

try (Transaction transaction = graphDB.beginTx()) {
Node character = /*lookup*/ ;
character.delete();
transaction .success();
}

Gotchas
●

no relationships must be attached when transaction commits

●

all properties will be automatically removed
Relationship CRUD (JVM)

try (Transaction transaction = graphDB.beginTx()) {
Node homer = /*lookup*/ ;
Node doughnut = /*lookup*/ ;
Relationship eating = homer.createRelationshipTo(
doughnut,
DynamicRelationshipType .withName("LOVES_EATING" )
);
eating.setProperty( "quantity" , Long.MAX_VALUE);
transaction .success();
}
Relationship CRUD (JVM)

try (Transaction transaction = graphDB.beginTx()) {
Node homer = /*lookup*/ ;
Node doughnut = /*lookup*/ ;
Relationship eating = homer.createRelationshipTo(
doughnut,
DynamicRelationshipType.withName("LOVES_EATING")
);
eating.setProperty( "quantity" , Long.MAX_VALUE);
transaction .success();
}

unrelated to
Node labels
Relationship CRUD (JVM)

try (Transaction transaction = graphDB.beginTx()) {
Node homer = /*lookup*/ ;
Node doughnut = /*lookup*/ ;
Relationship eating = homer.createRelationshipTo(
doughnut,
DynamicRelationshipType .withName("LOVES_EATING" )
);
eating.setProperty( "quantity" , Long.MAX_VALUE);
transaction .success();
}

Gotchas
●

relationship direction matters at query time

●

avoid human-eating doughnuts ;-)
Relationship CRUD (JVM)

try (Transaction transaction = graphDB.beginTx()) {
Relationship relationship = /*lookup*/ ;
relationship .delete();
transaction .success();
}
Relationship CRUD (JVM)

try (Transaction transaction = graphDB.beginTx()) {
Relationship relationship = /*lookup*/ ;
relationship .delete();
transaction .success();
}

Gotcha
●

a write lock is set on the relationship, as well as both start AND end
nodes of the relationship
Core API

Low Level
Transactions are ALWAYS required (v2.0)
Technical IDs are dangerous (findById)
have a look at github.com/sarmbruster/neo4j-uuid

SAME capabilities with REST API
QUERYING

DATA
Neo4J anatomy
Two strategies
IMPERATIVE

VERY extensive
Totally customizable

100% under your
responsability

DECLARATIVE

VERY intuitive
90% of your needs

No free lunch (yet)!
Might not be as performant
Two strategies

TRAVERSALS

CYPHER QL
(/GREMLIN)
Traversals
DEPTH FIRST

BREADTH FIRST
Traversals
Traversal - basic git

log

try (Transaction transaction = graphDB.beginTx()) {
for (Path position : Traversal.description()
.depthFirst()
.evaluator(toDepth(LOG_DEFAULT_SIZE))
.relationships(
DynRelType .withName("PARENT_COMMIT" ),
INCOMING
).traverse(headCommit)) {
Node currentNode = position.endNode;
logs.add(currentNode);
}
transaction .success();
}
Traversal - basic git

log

try (Transaction transaction = graphDB.beginTx()) {
for (Path position : Traversal.description()
.depthFirst()
.evaluator(toDepth(LOG_DEFAULT_SIZE))
lazy traversal

.relationships(

definition

DynRelType.withName("PARENT_COMMIT"),
Direction.INCOMING
).traverse(headCommit)) {

Node currentNode = position.endNode;
logs.add(currentNode);
}
transaction .success();
}
Traversal - basic git

log

try (Transaction transaction = graphDB.beginTx()) {
for (Path position : Traversal.description()
.depthFirst()
.evaluator(toDepth(LOG_DEFAULT_SIZE))
.relationships(
DynRelType.withName("PARENT_COMMIT" ),
INCOMING
).traverse(headCommit)) {
Node currentNode = position.endNode;
logs.add(currentNode);
}
transaction .success();
}

start traversal
with node
Traversal - basic git

log

try (Transaction transaction = graphDB.beginTx()) {
for (Path position : Traversal.description()
.depthFirst()
.evaluator(toDepth(LOG_DEFAULT_SIZE))
.relationships(
DynRelType.withName("PARENT_COMMIT" ),
INCOMING
).traverse(headCommit)) {
Node currentNode = position.endNode;
logs.add(currentNode);
}
transaction .success();
}

keeps track of
current position
& visited nodes/rels
Traversals

Extensive
but verbose
and error-prone

WE <3 ASCII ART!
Pattern matching and ASCII art

WE <3
CYPHER
Pattern matching and ASCII art
Pattern matching and ASCII art
Pattern matching and ASCII art
Pattern matching and ASCII art
Pattern matching and ASCII art
Pattern matching and ASCII art
Cypher syntax with <3

Cypher

()-->()
Cypher syntax with <3

Cypher

(A)-->(B)
Cypher syntax with <3

Cypher

LOVES

(A)-[:LOVES]->(B)
Cypher syntax with <3

Cypher
(C)<--(A)-->(B)-->(C)
A-->B-->C,A-->C
Cypher reads

START <lookup>

(optional)

MATCH <pattern>
WHERE <filtering>
RETURN <expression>
Cypher reads

MATCH (homer:HUMAN)-[:LOVES_EATING]->(doughnut:FOOD)
WHERE

homer.name = "Homer Simpson"

AND doughnut.brand = "Fattylicious!"
RETURN homer
Cypher reads

MATCH (sugg:CONTACT)-[:IN_CONTACT*2..10]-(me:CONTACT)
WHERE me.name = "Florent Biville"
AND me <> sugg
RETURN me, sugg
Cypher reads
RULES OF THUMB
● MATCH for results
● use WHERE to filter (WHERE

)

a-[:F]->b or NOT(a-[:F]->b)

● favour parameters over literals (exec. plan reuse)
● javacodegeeks.com: “optimizing Neo4j Cypher Queries”
Cypher writes

CREATE (UNIQUE) <expression>

MERGE <expression>
Cypher writes

CREATE (homer:HUMAN:DAD {name: "Homer Simpson"})
RETURN homer
Cypher writes

START homer = node:characters("name:Hom*")
MATCH (d:JUNK:FOOD)
WHERE d.brand = "Fattylicious!"
CREATE (homer)-[luv:LOVES_EATING {quantity:∞}]->(d)
RETURN luv
Cypher writes

MERGE (keanu:ACTOR {name:'Keanu Reeves'})
ON CREATE keanu
SET keanu.created = timestamp()
ON MATCH keanu
SET keanu.lastSeen = timestamp()
RETURN keanu
Cypher - I want moaaar

Declarative power
Super nice syntax
Evolutionary design with MERGE!
http://console.neo4j.org to try it out!
Cypher will the #1 way to query data!
OBJECT-GRAPH

MAPPING
With...
Spring Data
History ~2010

Rod Johnson,
Scala last poet

Emil Eifrem,
Neo Tech. founder & CEO
Spring Data
Familiar model for Spring apps

THIN common layer
Embraces diversity

MongoDB
Redis
Neo4J
ElasticSearch…

Current version

2.3.1.RELEASE
Vanilla Neo4J repositories with Spring
@Repository
public class BranchRepository {
public Relationship createBranch (Node p, Node c, Map<String,?> props) {
try (Transaction transaction = graphDB.beginTx()) {
Relationship relationship = p.createRelationshipTo(
c,
DynamicRelationshipType .name("HAS_BRANCH" )
);
for (Entry<String,?> entry:props.entrySet()) {
relationship .setProperty(entry .getKey(), entry .getValue());
}
transaction .success();
return relationship;
}}}
Vanilla Neo4J repositories with Spring
@Repository
public class BranchRepository {
public Relationship createBranch (Node p, Node commit, Map<String,?> props)
{
try (Transaction transaction = graphDB.beginTx()) {
Relationship relationship = p.createRelationshipTo(
commit,
DynamicRelationshipType .name("HAS_BRANCH" )
);
for (Entry<String,?> entry:props.entrySet()) {
relationship .setProperty(entry .getKey(), entry .getValue());
}
transaction .success();
return relationship;
Spring Data Neo4J repositories
public interface BranchRepository extends GraphRepository< Branch> {
// look ma! no code!
}
Moaaar Spring Data Neo4J repositories

public interface BranchRepository extends GraphRepository< Branch> {

Iterable<Branch> findByNameLike (String name);

@Query("MATCH (p:PROJECT)-[b:HAS_BRANCH]->(c:COMMIT) RETURN b" )
Page<Branch> lookMaIveGotPages ();

Branch findByNameAndCommitIdentifierLike (String name, String commit);
}
Moaaar Spring Data Neo4J repositories

public interface BranchRepository extends GraphRepository< Branch> {

Iterable<Branch> findByNameLike (String name);

@Query("MATCH (p:PROJECT)-[b:HAS_BRANCH]->(c:COMMIT) RETURN b" )

Cool things

Page<Branch> lookMaIveGotPages ();

● Branch findByNameAndCommitIdentifierLike (String
boilerplate methods already provided
}●

name, String commit);

you declare methods following a naming convention, Spring Data Neo4J
generates the right implementation for ya!

●

YOU EXPOSE YOUR DOMAIN, no Nodes, no Relationships!
Spring Data Neo4J node entities
@NodeEntity
public class Person {
@GraphId
private Long id;
@Indexed(indexName = "people", type=FULLTEXT)
private String name;
@RelatedTo (type="OWNS", enforceTargetType = true)
private Car car;
@RelatedToVia (type="FRIEND_OF" , direction = Direction.INCOMING)
private Iterable<Friendship> friendships;
@GraphTraversal (traversal = PeopleTraversalBuilder .class,
elementClass = Person.class, params = "persons")
private Iterable<Person> people;
}
Spring Data Neo4J relationship entities
@RelationshipEntity(type ="FRIEND_OF" )
public class Friendship {
@StartNode
private Person person;
@EndNode
private Dog humansBestFriend;
@GraphProperty /* optional here ;-) */
private Date since;
/**
* moaaaaar properties
*/
}
And much more

Neo4jTemplate
Geospatial queries

Cross-store support
Dynamic relationships
“Advanced” mapping
Conclusion
So much to talk about, so little time
● moaaar Cypher
● REST
○ standard API
○ unmanaged extensions
○ streaming
● Tinkerpop abstractions, http://www.tinkerpop.com/
● dataviz
○ auto : http://linkurio.us/, Neoclipse, Gephi
○ custom : d3.js, sigma.js…
● NeoAAS : http://www.graphenedb.com/, Heroku
● misc. : backup, batch-import, JDBC drivers
And one more thing

AssertJ-Neo4J 1.0 is coming soon!
Fluent test assertions for Neo4J
https://github.com/joel-costigliola/assertj-neo4j
Soft Shake Event / A soft introduction to Neo4J

More Related Content

What's hot

Clojure for Java developers - Stockholm
Clojure for Java developers - StockholmClojure for Java developers - Stockholm
Clojure for Java developers - Stockholm
Jan Kronquist
 

What's hot (20)

tutorial5
tutorial5tutorial5
tutorial5
 
RealmDB for Android
RealmDB for AndroidRealmDB for Android
RealmDB for Android
 
[DSC 2016] 系列活動:李泳泉 / 星火燎原 - Spark 機器學習初探
[DSC 2016] 系列活動:李泳泉 / 星火燎原 - Spark 機器學習初探[DSC 2016] 系列活動:李泳泉 / 星火燎原 - Spark 機器學習初探
[DSC 2016] 系列活動:李泳泉 / 星火燎原 - Spark 機器學習初探
 
OSDC.fr 2012 :: Cascalog : progammation logique pour Hadoop
OSDC.fr 2012 :: Cascalog : progammation logique pour HadoopOSDC.fr 2012 :: Cascalog : progammation logique pour Hadoop
OSDC.fr 2012 :: Cascalog : progammation logique pour Hadoop
 
Photo-realistic Single Image Super-resolution using a Generative Adversarial ...
Photo-realistic Single Image Super-resolution using a Generative Adversarial ...Photo-realistic Single Image Super-resolution using a Generative Adversarial ...
Photo-realistic Single Image Super-resolution using a Generative Adversarial ...
 
LSGAN - SIMPle(Simple Idea Meaningful Performance Level up)
LSGAN - SIMPle(Simple Idea Meaningful Performance Level up)LSGAN - SIMPle(Simple Idea Meaningful Performance Level up)
LSGAN - SIMPle(Simple Idea Meaningful Performance Level up)
 
What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)
 
Rainer Grimm, “Functional Programming in C++11”
Rainer Grimm, “Functional Programming in C++11”Rainer Grimm, “Functional Programming in C++11”
Rainer Grimm, “Functional Programming in C++11”
 
The Macronomicon
The MacronomiconThe Macronomicon
The Macronomicon
 
COLLADA & WebGL
COLLADA & WebGLCOLLADA & WebGL
COLLADA & WebGL
 
Polyglot persistence for Java developers - moving out of the relational comfo...
Polyglot persistence for Java developers - moving out of the relational comfo...Polyglot persistence for Java developers - moving out of the relational comfo...
Polyglot persistence for Java developers - moving out of the relational comfo...
 
The Language for future-julia
The Language for future-juliaThe Language for future-julia
The Language for future-julia
 
Clojure for Java developers - Stockholm
Clojure for Java developers - StockholmClojure for Java developers - Stockholm
Clojure for Java developers - Stockholm
 
Coding Ajax
Coding AjaxCoding Ajax
Coding Ajax
 
Garbage collector in python
Garbage collector in pythonGarbage collector in python
Garbage collector in python
 
JavaOne 2013 - Clojure for Java Developers
JavaOne 2013 - Clojure for Java DevelopersJavaOne 2013 - Clojure for Java Developers
JavaOne 2013 - Clojure for Java Developers
 
Why learn new programming languages
Why learn new programming languagesWhy learn new programming languages
Why learn new programming languages
 
Clojure class
Clojure classClojure class
Clojure class
 
Functional microscope - Lenses in C++
Functional microscope - Lenses in C++Functional microscope - Lenses in C++
Functional microscope - Lenses in C++
 
COSCUP: Introduction to Julia
COSCUP: Introduction to JuliaCOSCUP: Introduction to Julia
COSCUP: Introduction to Julia
 

Viewers also liked (6)

[FR] Introduction à Spring Data Neo4j 3.x
[FR] Introduction à Spring Data Neo4j 3.x[FR] Introduction à Spring Data Neo4j 3.x
[FR] Introduction à Spring Data Neo4j 3.x
 
Why Neo4J is awesome in 5 slides
Why Neo4J is awesome in 5 slidesWhy Neo4J is awesome in 5 slides
Why Neo4J is awesome in 5 slides
 
Hands on Neo4J - Duchess France/Zenexity - 25/09/2013
Hands on Neo4J - Duchess France/Zenexity - 25/09/2013Hands on Neo4J - Duchess France/Zenexity - 25/09/2013
Hands on Neo4J - Duchess France/Zenexity - 25/09/2013
 
A general introduction to Spring Data / Neo4J
A general introduction to Spring Data / Neo4JA general introduction to Spring Data / Neo4J
A general introduction to Spring Data / Neo4J
 
(R)évolutionnez vos bases de données avec Liquibase
(R)évolutionnez vos bases de données avec Liquibase(R)évolutionnez vos bases de données avec Liquibase
(R)évolutionnez vos bases de données avec Liquibase
 
Liquibase en action
Liquibase en actionLiquibase en action
Liquibase en action
 

Similar to Soft Shake Event / A soft introduction to Neo4J

mobl presentation @ IHomer
mobl presentation @ IHomermobl presentation @ IHomer
mobl presentation @ IHomer
zefhemel
 
MLconf NYC Shan Shan Huang
MLconf NYC Shan Shan HuangMLconf NYC Shan Shan Huang
MLconf NYC Shan Shan Huang
MLconf
 
Introduction into scalable graph analysis with Apache Giraph and Spark GraphX
Introduction into scalable graph analysis with Apache Giraph and Spark GraphXIntroduction into scalable graph analysis with Apache Giraph and Spark GraphX
Introduction into scalable graph analysis with Apache Giraph and Spark GraphX
rhatr
 
Ft10 de smet
Ft10 de smetFt10 de smet
Ft10 de smet
nkaluva
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
Dmitry Buzdin
 
Wprowadzenie do technologi Big Data i Apache Hadoop
Wprowadzenie do technologi Big Data i Apache HadoopWprowadzenie do technologi Big Data i Apache Hadoop
Wprowadzenie do technologi Big Data i Apache Hadoop
Sages
 

Similar to Soft Shake Event / A soft introduction to Neo4J (20)

Java/Scala Lab: Борис Трофимов - Обжигающая Big Data.
Java/Scala Lab: Борис Трофимов - Обжигающая Big Data.Java/Scala Lab: Борис Трофимов - Обжигающая Big Data.
Java/Scala Lab: Борис Трофимов - Обжигающая Big Data.
 
mobl presentation @ IHomer
mobl presentation @ IHomermobl presentation @ IHomer
mobl presentation @ IHomer
 
Groovy On Trading Desk (2010)
Groovy On Trading Desk (2010)Groovy On Trading Desk (2010)
Groovy On Trading Desk (2010)
 
Cloud jpl
Cloud jplCloud jpl
Cloud jpl
 
Hadoop trainingin bangalore
Hadoop trainingin bangaloreHadoop trainingin bangalore
Hadoop trainingin bangalore
 
Scalding Big (Ad)ta
Scalding Big (Ad)taScalding Big (Ad)ta
Scalding Big (Ad)ta
 
MLconf NYC Shan Shan Huang
MLconf NYC Shan Shan HuangMLconf NYC Shan Shan Huang
MLconf NYC Shan Shan Huang
 
Full stack analytics with Hadoop 2
Full stack analytics with Hadoop 2Full stack analytics with Hadoop 2
Full stack analytics with Hadoop 2
 
Apache Flink & Graph Processing
Apache Flink & Graph ProcessingApache Flink & Graph Processing
Apache Flink & Graph Processing
 
Graph computation
Graph computationGraph computation
Graph computation
 
Introduction into scalable graph analysis with Apache Giraph and Spark GraphX
Introduction into scalable graph analysis with Apache Giraph and Spark GraphXIntroduction into scalable graph analysis with Apache Giraph and Spark GraphX
Introduction into scalable graph analysis with Apache Giraph and Spark GraphX
 
Tips And Tricks For Bioinformatics Software Engineering
Tips And Tricks For Bioinformatics Software EngineeringTips And Tricks For Bioinformatics Software Engineering
Tips And Tricks For Bioinformatics Software Engineering
 
Building a Scalable Distributed Stats Infrastructure with Storm and KairosDB
Building a Scalable Distributed Stats Infrastructure with Storm and KairosDBBuilding a Scalable Distributed Stats Infrastructure with Storm and KairosDB
Building a Scalable Distributed Stats Infrastructure with Storm and KairosDB
 
Building Go Web Apps
Building Go Web AppsBuilding Go Web Apps
Building Go Web Apps
 
Shooting the Rapids
Shooting the RapidsShooting the Rapids
Shooting the Rapids
 
Ft10 de smet
Ft10 de smetFt10 de smet
Ft10 de smet
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
Wprowadzenie do technologi Big Data i Apache Hadoop
Wprowadzenie do technologi Big Data i Apache HadoopWprowadzenie do technologi Big Data i Apache Hadoop
Wprowadzenie do technologi Big Data i Apache Hadoop
 
End-to-end Big Data Projects with Python - StampedeCon Big Data Conference 2017
End-to-end Big Data Projects with Python - StampedeCon Big Data Conference 2017End-to-end Big Data Projects with Python - StampedeCon Big Data Conference 2017
End-to-end Big Data Projects with Python - StampedeCon Big Data Conference 2017
 
Introduction to Scalding and Monoids
Introduction to Scalding and MonoidsIntroduction to Scalding and Monoids
Introduction to Scalding and Monoids
 

Recently uploaded

Revolutionizing SAP® Processes with Automation and Artificial Intelligence
Revolutionizing SAP® Processes with Automation and Artificial IntelligenceRevolutionizing SAP® Processes with Automation and Artificial Intelligence
Revolutionizing SAP® Processes with Automation and Artificial Intelligence
Precisely
 
Harnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptx
Harnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptxHarnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptx
Harnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptx
FIDO Alliance
 
“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf
“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf
“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf
Muhammad Subhan
 

Recently uploaded (20)

Continuing Bonds Through AI: A Hermeneutic Reflection on Thanabots
Continuing Bonds Through AI: A Hermeneutic Reflection on ThanabotsContinuing Bonds Through AI: A Hermeneutic Reflection on Thanabots
Continuing Bonds Through AI: A Hermeneutic Reflection on Thanabots
 
Overview of Hyperledger Foundation
Overview of Hyperledger FoundationOverview of Hyperledger Foundation
Overview of Hyperledger Foundation
 
Frisco Automating Purchase Orders with MuleSoft IDP- May 10th, 2024.pptx.pdf
Frisco Automating Purchase Orders with MuleSoft IDP- May 10th, 2024.pptx.pdfFrisco Automating Purchase Orders with MuleSoft IDP- May 10th, 2024.pptx.pdf
Frisco Automating Purchase Orders with MuleSoft IDP- May 10th, 2024.pptx.pdf
 
1111 ChatGPT Prompts PDF Free Download - Prompts for ChatGPT
1111 ChatGPT Prompts PDF Free Download - Prompts for ChatGPT1111 ChatGPT Prompts PDF Free Download - Prompts for ChatGPT
1111 ChatGPT Prompts PDF Free Download - Prompts for ChatGPT
 
(Explainable) Data-Centric AI: what are you explaininhg, and to whom?
(Explainable) Data-Centric AI: what are you explaininhg, and to whom?(Explainable) Data-Centric AI: what are you explaininhg, and to whom?
(Explainable) Data-Centric AI: what are you explaininhg, and to whom?
 
Intro to Passkeys and the State of Passwordless.pptx
Intro to Passkeys and the State of Passwordless.pptxIntro to Passkeys and the State of Passwordless.pptx
Intro to Passkeys and the State of Passwordless.pptx
 
2024 May Patch Tuesday
2024 May Patch Tuesday2024 May Patch Tuesday
2024 May Patch Tuesday
 
WebAssembly is Key to Better LLM Performance
WebAssembly is Key to Better LLM PerformanceWebAssembly is Key to Better LLM Performance
WebAssembly is Key to Better LLM Performance
 
Revolutionizing SAP® Processes with Automation and Artificial Intelligence
Revolutionizing SAP® Processes with Automation and Artificial IntelligenceRevolutionizing SAP® Processes with Automation and Artificial Intelligence
Revolutionizing SAP® Processes with Automation and Artificial Intelligence
 
ERP Contender Series: Acumatica vs. Sage Intacct
ERP Contender Series: Acumatica vs. Sage IntacctERP Contender Series: Acumatica vs. Sage Intacct
ERP Contender Series: Acumatica vs. Sage Intacct
 
Generative AI Use Cases and Applications.pdf
Generative AI Use Cases and Applications.pdfGenerative AI Use Cases and Applications.pdf
Generative AI Use Cases and Applications.pdf
 
Cyber Insurance - RalphGilot - Embry-Riddle Aeronautical University.pptx
Cyber Insurance - RalphGilot - Embry-Riddle Aeronautical University.pptxCyber Insurance - RalphGilot - Embry-Riddle Aeronautical University.pptx
Cyber Insurance - RalphGilot - Embry-Riddle Aeronautical University.pptx
 
AI mind or machine power point presentation
AI mind or machine power point presentationAI mind or machine power point presentation
AI mind or machine power point presentation
 
Harnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptx
Harnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptxHarnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptx
Harnessing Passkeys in the Battle Against AI-Powered Cyber Threats.pptx
 
The Metaverse: Are We There Yet?
The  Metaverse:    Are   We  There  Yet?The  Metaverse:    Are   We  There  Yet?
The Metaverse: Are We There Yet?
 
“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf
“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf
“Iamnobody89757” Understanding the Mysterious of Digital Identity.pdf
 
Event-Driven Architecture Masterclass: Integrating Distributed Data Stores Ac...
Event-Driven Architecture Masterclass: Integrating Distributed Data Stores Ac...Event-Driven Architecture Masterclass: Integrating Distributed Data Stores Ac...
Event-Driven Architecture Masterclass: Integrating Distributed Data Stores Ac...
 
Design and Development of a Provenance Capture Platform for Data Science
Design and Development of a Provenance Capture Platform for Data ScienceDesign and Development of a Provenance Capture Platform for Data Science
Design and Development of a Provenance Capture Platform for Data Science
 
Microsoft CSP Briefing Pre-Engagement - Questionnaire
Microsoft CSP Briefing Pre-Engagement - QuestionnaireMicrosoft CSP Briefing Pre-Engagement - Questionnaire
Microsoft CSP Briefing Pre-Engagement - Questionnaire
 
Top 10 CodeIgniter Development Companies
Top 10 CodeIgniter Development CompaniesTop 10 CodeIgniter Development Companies
Top 10 CodeIgniter Development Companies
 

Soft Shake Event / A soft introduction to Neo4J

  • 1. A soft introduction to (Reality)-[:IS_A]->(Graph) @fbiville / @LateraIThoughts / florent.biville.net / www.lateral-thoughts.com
  • 2. What we have always known selection sort (O(n2))
  • 3. What we have always known selection sort (O(n2)) | heap sort (O(n*log(n))
  • 4. What we have always known selection sort (O(n2)) | heap sort (O(n*log(n)) same algorithm, different data structure, better execution time !
  • 5. What we have always known 1 data structure 1 usage
  • 6. One NOSQL lesson? 1 data STORE 1 usage
  • 7. One NOSQL lesson? polyglot persistence, anyone ?
  • 8.
  • 9. ZOOM on Graph Databases graph = nodes/vertices + edges/relationships/arcs
  • 10. Graph DB : a common model property graph = nodes + labeled relationships + K/V pairs
  • 11. Graph DB : a common model property graph = labeledneov2 nodes + labeled relationships + K/V pairs
  • 13. Property Graph DBs WHY DO THEY KICK ASS?
  • 16. Graph-based computing Intuitive model Whiteboard-friendliness Expressive querying Pregel (GOOG), TAO (FB) Powerful analyses Pattern matching, path finding...
  • 17. A glimpse at usecases: mantra RELATIONSHIPS ARE AS IMPORTANT AS E N T I T I E S
  • 18. A glimpse at usecases Recommendations People I may know ex: people known by contacts I have worked with in the past
  • 19. A glimpse at usecases Recommendations People I may know ex: people known by contacts I have worked with in the past Products I should buy ex: people who bought “Twilight” and “Justin Bieber biography” like you also bought “The ultimate emo guide”
  • 20. A glimpse at usecases Recommendations People I may know ex: people known by contacts I have worked with in the past Products I should buy ex: people who bought “Twilight” and “Justin Bieber biography” like you also bought “The ultimate emo guide” Movies I should watch with whom and where...
  • 21. A glimpse at usecases Pattern detection Fraud ex: many IPs from Fraudistan have made a purchase of game X in the last hour
  • 22. A glimpse at usecases Pattern detection Fraud ex: many IPs from Fraudistan have made a purchase of game X in the last hour Disease detection ex: DNA sequencing
  • 23. A glimpse at usecases Pattern detection Fraud ex: many IPs from Fraudistan have made a purchase of game X in the last hour Disease detection ex: DNA sequencing Trend detection ex: the term Flu has been tweeted 789% times more in Guatemala area in the last 24 hours
  • 24. A glimpse at usecases Path finding Genealogy ex: is François Mitterand related to Elizabeth II ? (yes)
  • 25. A glimpse at usecases Path finding Genealogy ex: is François Mitterand related to Elizabeth II ? (yes) Navigation ex: what is the cheapest way to go to a sushi < 15€ for me (Place de Clichy) and my friend (Place d’Italie)?
  • 26. A glimpse at usecases Path finding Genealogy ex: is François Mitterand related to Elizabeth II ? (yes) Navigation ex: what is the cheapest way to go to a sushi < 15€ for me (Place de Clichy) and my friend (Place d’Italie)? Impact analysis ex: which customers are impacted if network switch XYZ fails?
  • 27. A glimpse at usecases and more... Topological ordering ex: given a set of dependencies, in which order should I include them? Community detection ex: tag clustering on annotated resources to detect groups of interest (targeted advertising) and much more...
  • 28. A glimpse at usecases http://www.opentreeoflife.org/ http://bio4j.com/ http://www.reco4j.org/ https://github.com/neo4j-contrib/graphgist/wiki
  • 31. Neo4J - the origins Circa 2000, somewhere in Sweden 2 swedish guys hacking in a garage
  • 32. Neo4J - the origins Dialogue - Man, I cannot stand Informix anymore - Right, we’ve pushed it to the limit - All these documents, these workflows… - Right, it’s way too densely connected. - Connected… connections? CONNECTIONS??
  • 33.
  • 34. Flash-forward: Neo Technology! 1 company Neo Technology 1 main product Neo4J ~50 employees All over the world Sweden, US, Germany, France, Malaysia, NZ...
  • 35. Neo4J - moaar facts & figures Versions 2.0.0.M06 / 1.9.4 Licenses GPL, AGPL, OEM, Commercial 235 nodes 34_359_738_368 235 relationships > 236 properties at most 238 … capacity can be tailored on demand
  • 37. GRAPH ON DISK (roughly) original presentation: http://www.ustream.tv/channel/neo4j
  • 38.
  • 39.
  • 40.
  • 41.
  • 44. Node CRUD (JVM) GraphDatabaseService graphDB = new TestGraphDatabaseFactory () .newImpermanentDatabase(); try (Transaction transaction = graphDB.beginTx()) { Node character =graphDB.createNode( DynamicLabel .label("CHARACTER" )); character.setProperty( "name", "Homer Simpson" ); transaction .success(); }
  • 45. Node CRUD (JVM) officially distributed test version! GraphDatabaseService graphDB = new TestGraphDatabaseFactory() .newImpermanentDatabase(); try (Transaction transaction = graphDB.beginTx()) { Node character =graphDB.createNode( DynamicLabel .label("CHARACTER" )); character.setProperty( "name", "Homer Simpson" ); transaction .success(); }
  • 46. Node CRUD (JVM) GraphDatabaseService graphDB = new TestGraphDatabaseFactory () .newImpermanentDatabase(); try (Transaction transaction = graphDB.beginTx()) { Node character =graphDB.createNode( DynamicLabel .label("CHARACTER" )); character.setProperty( "name", "Homer Simpson" ); transaction .success(); } transaction is MANDATORY Java 7 required since 2.0
  • 47. Node CRUD (JVM) GraphDatabaseService graphDB = new TestGraphDatabaseFactory () .newImpermanentDatabase(); try (Transaction transaction = graphDB.beginTx()) { Node character =graphDB.createNode( DynamicLabel.label("CHARACTER")); character.setProperty( "name", "Homer Simpson" ); transaction .success(); } labels are a way to semi-structure your nodes (since 2.0)
  • 48. Node CRUD (JVM) try (Transaction transaction = graphDB.beginTx()) { for (Node node: graphDB.findNodesByLabelAndProperty( DynamicLabel .label("CHARACTER" ), "name", "Homer Simpson" )) { /* do something very useful */ } transaction .success(); }
  • 49. Node CRUD (JVM) try (Transaction transaction = graphDB.beginTx()) { for (Node node: graphDB.findNodesByLabelAndProperty( DynamicLabel .label("CHARACTER" ), "name", "Homer Simpson" )) { /* do something very useful */ } transaction .success(); } Gotchas ● avoid graphDB.findById !!! ● transaction is MANDATORY for reads as well (new in 2.0)
  • 50. Node CRUD (JVM) try (Transaction transaction = graphDB.beginTx()) { Node character = /*lookup*/ ; character.delete(); transaction .success(); }
  • 51. Node CRUD (JVM) try (Transaction transaction = graphDB.beginTx()) { Node character = /*lookup*/ ; character.delete(); transaction .success(); } Gotchas ● no relationships must be attached when transaction commits ● all properties will be automatically removed
  • 52. Relationship CRUD (JVM) try (Transaction transaction = graphDB.beginTx()) { Node homer = /*lookup*/ ; Node doughnut = /*lookup*/ ; Relationship eating = homer.createRelationshipTo( doughnut, DynamicRelationshipType .withName("LOVES_EATING" ) ); eating.setProperty( "quantity" , Long.MAX_VALUE); transaction .success(); }
  • 53. Relationship CRUD (JVM) try (Transaction transaction = graphDB.beginTx()) { Node homer = /*lookup*/ ; Node doughnut = /*lookup*/ ; Relationship eating = homer.createRelationshipTo( doughnut, DynamicRelationshipType.withName("LOVES_EATING") ); eating.setProperty( "quantity" , Long.MAX_VALUE); transaction .success(); } unrelated to Node labels
  • 54. Relationship CRUD (JVM) try (Transaction transaction = graphDB.beginTx()) { Node homer = /*lookup*/ ; Node doughnut = /*lookup*/ ; Relationship eating = homer.createRelationshipTo( doughnut, DynamicRelationshipType .withName("LOVES_EATING" ) ); eating.setProperty( "quantity" , Long.MAX_VALUE); transaction .success(); } Gotchas ● relationship direction matters at query time ● avoid human-eating doughnuts ;-)
  • 55. Relationship CRUD (JVM) try (Transaction transaction = graphDB.beginTx()) { Relationship relationship = /*lookup*/ ; relationship .delete(); transaction .success(); }
  • 56. Relationship CRUD (JVM) try (Transaction transaction = graphDB.beginTx()) { Relationship relationship = /*lookup*/ ; relationship .delete(); transaction .success(); } Gotcha ● a write lock is set on the relationship, as well as both start AND end nodes of the relationship
  • 57. Core API Low Level Transactions are ALWAYS required (v2.0) Technical IDs are dangerous (findById) have a look at github.com/sarmbruster/neo4j-uuid SAME capabilities with REST API
  • 60. Two strategies IMPERATIVE VERY extensive Totally customizable 100% under your responsability DECLARATIVE VERY intuitive 90% of your needs No free lunch (yet)! Might not be as performant
  • 64. Traversal - basic git log try (Transaction transaction = graphDB.beginTx()) { for (Path position : Traversal.description() .depthFirst() .evaluator(toDepth(LOG_DEFAULT_SIZE)) .relationships( DynRelType .withName("PARENT_COMMIT" ), INCOMING ).traverse(headCommit)) { Node currentNode = position.endNode; logs.add(currentNode); } transaction .success(); }
  • 65. Traversal - basic git log try (Transaction transaction = graphDB.beginTx()) { for (Path position : Traversal.description() .depthFirst() .evaluator(toDepth(LOG_DEFAULT_SIZE)) lazy traversal .relationships( definition DynRelType.withName("PARENT_COMMIT"), Direction.INCOMING ).traverse(headCommit)) { Node currentNode = position.endNode; logs.add(currentNode); } transaction .success(); }
  • 66. Traversal - basic git log try (Transaction transaction = graphDB.beginTx()) { for (Path position : Traversal.description() .depthFirst() .evaluator(toDepth(LOG_DEFAULT_SIZE)) .relationships( DynRelType.withName("PARENT_COMMIT" ), INCOMING ).traverse(headCommit)) { Node currentNode = position.endNode; logs.add(currentNode); } transaction .success(); } start traversal with node
  • 67. Traversal - basic git log try (Transaction transaction = graphDB.beginTx()) { for (Path position : Traversal.description() .depthFirst() .evaluator(toDepth(LOG_DEFAULT_SIZE)) .relationships( DynRelType.withName("PARENT_COMMIT" ), INCOMING ).traverse(headCommit)) { Node currentNode = position.endNode; logs.add(currentNode); } transaction .success(); } keeps track of current position & visited nodes/rels
  • 69. Pattern matching and ASCII art WE <3 CYPHER
  • 70. Pattern matching and ASCII art
  • 71. Pattern matching and ASCII art
  • 72. Pattern matching and ASCII art
  • 73. Pattern matching and ASCII art
  • 74. Pattern matching and ASCII art
  • 75. Pattern matching and ASCII art
  • 76. Cypher syntax with <3 Cypher ()-->()
  • 77. Cypher syntax with <3 Cypher (A)-->(B)
  • 78. Cypher syntax with <3 Cypher LOVES (A)-[:LOVES]->(B)
  • 79. Cypher syntax with <3 Cypher (C)<--(A)-->(B)-->(C) A-->B-->C,A-->C
  • 80. Cypher reads START <lookup> (optional) MATCH <pattern> WHERE <filtering> RETURN <expression>
  • 81. Cypher reads MATCH (homer:HUMAN)-[:LOVES_EATING]->(doughnut:FOOD) WHERE homer.name = "Homer Simpson" AND doughnut.brand = "Fattylicious!" RETURN homer
  • 82. Cypher reads MATCH (sugg:CONTACT)-[:IN_CONTACT*2..10]-(me:CONTACT) WHERE me.name = "Florent Biville" AND me <> sugg RETURN me, sugg
  • 83. Cypher reads RULES OF THUMB ● MATCH for results ● use WHERE to filter (WHERE ) a-[:F]->b or NOT(a-[:F]->b) ● favour parameters over literals (exec. plan reuse) ● javacodegeeks.com: “optimizing Neo4j Cypher Queries”
  • 84. Cypher writes CREATE (UNIQUE) <expression> MERGE <expression>
  • 85. Cypher writes CREATE (homer:HUMAN:DAD {name: "Homer Simpson"}) RETURN homer
  • 86. Cypher writes START homer = node:characters("name:Hom*") MATCH (d:JUNK:FOOD) WHERE d.brand = "Fattylicious!" CREATE (homer)-[luv:LOVES_EATING {quantity:∞}]->(d) RETURN luv
  • 87. Cypher writes MERGE (keanu:ACTOR {name:'Keanu Reeves'}) ON CREATE keanu SET keanu.created = timestamp() ON MATCH keanu SET keanu.lastSeen = timestamp() RETURN keanu
  • 88. Cypher - I want moaaar Declarative power Super nice syntax Evolutionary design with MERGE! http://console.neo4j.org to try it out! Cypher will the #1 way to query data!
  • 91. Spring Data History ~2010 Rod Johnson, Scala last poet Emil Eifrem, Neo Tech. founder & CEO
  • 92. Spring Data Familiar model for Spring apps THIN common layer Embraces diversity MongoDB Redis Neo4J ElasticSearch… Current version 2.3.1.RELEASE
  • 93. Vanilla Neo4J repositories with Spring @Repository public class BranchRepository { public Relationship createBranch (Node p, Node c, Map<String,?> props) { try (Transaction transaction = graphDB.beginTx()) { Relationship relationship = p.createRelationshipTo( c, DynamicRelationshipType .name("HAS_BRANCH" ) ); for (Entry<String,?> entry:props.entrySet()) { relationship .setProperty(entry .getKey(), entry .getValue()); } transaction .success(); return relationship; }}}
  • 94. Vanilla Neo4J repositories with Spring @Repository public class BranchRepository { public Relationship createBranch (Node p, Node commit, Map<String,?> props) { try (Transaction transaction = graphDB.beginTx()) { Relationship relationship = p.createRelationshipTo( commit, DynamicRelationshipType .name("HAS_BRANCH" ) ); for (Entry<String,?> entry:props.entrySet()) { relationship .setProperty(entry .getKey(), entry .getValue()); } transaction .success(); return relationship;
  • 95. Spring Data Neo4J repositories public interface BranchRepository extends GraphRepository< Branch> { // look ma! no code! }
  • 96. Moaaar Spring Data Neo4J repositories public interface BranchRepository extends GraphRepository< Branch> { Iterable<Branch> findByNameLike (String name); @Query("MATCH (p:PROJECT)-[b:HAS_BRANCH]->(c:COMMIT) RETURN b" ) Page<Branch> lookMaIveGotPages (); Branch findByNameAndCommitIdentifierLike (String name, String commit); }
  • 97. Moaaar Spring Data Neo4J repositories public interface BranchRepository extends GraphRepository< Branch> { Iterable<Branch> findByNameLike (String name); @Query("MATCH (p:PROJECT)-[b:HAS_BRANCH]->(c:COMMIT) RETURN b" ) Cool things Page<Branch> lookMaIveGotPages (); ● Branch findByNameAndCommitIdentifierLike (String boilerplate methods already provided }● name, String commit); you declare methods following a naming convention, Spring Data Neo4J generates the right implementation for ya! ● YOU EXPOSE YOUR DOMAIN, no Nodes, no Relationships!
  • 98. Spring Data Neo4J node entities @NodeEntity public class Person { @GraphId private Long id; @Indexed(indexName = "people", type=FULLTEXT) private String name; @RelatedTo (type="OWNS", enforceTargetType = true) private Car car; @RelatedToVia (type="FRIEND_OF" , direction = Direction.INCOMING) private Iterable<Friendship> friendships; @GraphTraversal (traversal = PeopleTraversalBuilder .class, elementClass = Person.class, params = "persons") private Iterable<Person> people; }
  • 99. Spring Data Neo4J relationship entities @RelationshipEntity(type ="FRIEND_OF" ) public class Friendship { @StartNode private Person person; @EndNode private Dog humansBestFriend; @GraphProperty /* optional here ;-) */ private Date since; /** * moaaaaar properties */ }
  • 100. And much more Neo4jTemplate Geospatial queries Cross-store support Dynamic relationships “Advanced” mapping
  • 102. So much to talk about, so little time ● moaaar Cypher ● REST ○ standard API ○ unmanaged extensions ○ streaming ● Tinkerpop abstractions, http://www.tinkerpop.com/ ● dataviz ○ auto : http://linkurio.us/, Neoclipse, Gephi ○ custom : d3.js, sigma.js… ● NeoAAS : http://www.graphenedb.com/, Heroku ● misc. : backup, batch-import, JDBC drivers
  • 103. And one more thing AssertJ-Neo4J 1.0 is coming soon! Fluent test assertions for Neo4J https://github.com/joel-costigliola/assertj-neo4j