Upload
florent-biville
View
118
Download
5
Tags:
Embed Size (px)
DESCRIPTION
GraphDB Meetup Paris : 1st of October.
Citation preview
`whoami`
@fbiville @LateraIThoughts
:WORKS_FOR
:IS_R
EA
CH
AB
LE
{on: “Twitter”}
:IS_R
EA
CH
AB
LE
{on:
“Tw
itter
”}
:LOVES :IS_PARTNER_WITH
Calendar
ConferenceOctober / http://tinyurl.com/soft-shake-neo4j
Traininghttp://www.lateral-thoughts.com/formation-neo4j
BBL : just ping me!http://www.brownbaglunch.fr/baggers.html#Florent_Biville
On one side: graph databases!
Flock DB
On one side: graph databases!
Flock DBVERY
DYN
AMIC
LANDSC
APE
On the other side: the enterprise
On the other side: the enterprise
LIVE L
ONG AND P
ROSP
ER
The Enterprise Architecture
● Entities
● DAO
● Service
● Controllers
The Enterprise Architecture
● Entities
● DAO
● Service
● Controllers
?
featuring an Oh Real Monster!
Object-Relational Mapping
Applies only to Relational DBMS
Lowest common denominator
80% easy
20% … painful
Java and ORMs
Java Persistence API
JSR 220 - JSR 317
Main implementors
● EclipseLink
● Apache OpenJPA
● Hibernate
@Entity
@Table(name = "channels")
public class Channel {
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", nullable = false)
private long id;
@Column(name = "title", nullable = false,
unique = true)
private String title = "";
@Column(name = "description", nullable =
false)
private String description = "";
// [...]
}
Java and ORMs
Java Persistence API
JSR 220 - JSR 317
Main implementors
● EclipseLink
● Apache OpenJPA
● Hibernate
@Repository
public class CastRepository implements /.../ {
@PersistenceContext
private EntityManager entityManager;
@Override
@Transactional
public void delete(final Cast cast) {
entityManager.remove(cast);
}
@Override
@Transactional(readOnly = true)
public Cast findById(final long id) {
checkArgument(id >= 0);
return entityManager.find(Cast.class, id);
}
}
Java and ORMs: the good parts
Familiar programming model
● @Transactional [SPRING]
● @Entity, @Table...
● @Repository [SPRING]
Java and ORMs: the bad parts
Defines its own universe
see JPA entity lifecycle ;-(
Relation-Objects = 2 <> paradigms!
1+n query problem
inheritance strategies
SQL knowledge needed -> abstraction leak
What model REALLY is relational? :)
Why does Neo4J kick ass? cuz...
Graph = generic Data Structure
...and powerful ;-)
Natural fit with objects
Frictionless mapping!
Mapping with Neo4J?!
BUT No predefined schema
Labeled nodes can be very <>
Same with relationships
Schema-optionality = a problem?
see the awesome GraphGist challenge!
Schema-optionality = a problem?
Typical apps do not handle
gazillion of entities
More like a finite number
Let’s map then!
First approach: Hibernate OGM
Reuses Hibernate Core
Supports simple JP-QL queries
Support for Neo4J is a WIP
Let’s map then!
First approach: Hibernate OGM
Reuses Hibernate Core
Supports simple JP-QL queries
Support for Neo4J is a WIP
Lowest Common Denominator
Let’s map then!
Second approach: Tinkerpop Frames
Multi-graph DB support (Blueprints interface)
REST support with Tinkerpop REXSTER
Querying with Gremlin
Let’s map then!
Third approach: Spring Data Neo4J
Spring / Spring Data philosophy
Templates
Entities, “magic” repositories, @Transactional
Cypher support
Multi-store support
Spring Data
History ~2010
Rod Johnson, (was) VMWare
Emil Eifrem, Neo Technology
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”
@Repositorypublic class BranchRepository {
private final GraphDatabaseService graphDB;
public Relationship createBranch(Node project, Node commit, Map<String,?> properties) {
try (Transaction tx = graphDB.beginTx()) {Relationship relationship = project.createRelationshipTo(
commit,DynamicRelationshipType.name("HAS_BRANCH")
);for (Entry<String,?> entry:properties.entrySet()) {
relationship.setProperty(entry.getKey(), entry.getValue());}tx.success();return relationship;
}}
vanilla Neo4J “repositories”
@Repositorypublic class BranchRepository {
private final GraphDatabaseService graphDB;
public Relationship createBranch(Node project, Node commit, Map<String,?> properties) {
try (Transaction tx = graphDB.beginTx()) {Relationship relationship = project.createRelationshipTo(
commit,DynamicRelationshipType.name("HAS_BRANCH")
);for (Entry<String,?> entry:properties.entrySet()) {
relationship.setProperty(entry.getKey(), entry.getValue());}tx.success();return relationship;
}}
vanilla Neo4J “repositories”
@Repositorypublic class BranchRepository {
private final GraphDatabaseService graphDB;
public Relationship createBranch(Node project, Node commit, Map<String,?> properties) {
try (Transaction tx = graphDB.beginTx()) {Relationship relationship = project.createRelationshipTo(
commit,DynamicRelationshipType.name("HAS_BRANCH")
);for (Entry<String,?> entry:properties.entrySet()) {
relationship.setProperty(entry.getKey(), entry.getValue());}tx.success();return relationship;
}}
Spring Data Neo4J repositories
public interface BranchRepository extends GraphRepository<Branch> {
}
Spring Data Neo4J repositories
What’s behind GraphRepository
Spring Data Commons - Repository
Marker interface, automatic discovery
Spring Data Commons - CRUDRepository
Create/Read/Update/Delete “boilerplate” operations
Spring Data Commons - PagingAndSortingRepository
Pagination/sorting facilities
Spring Data Neo4J - IndexRepository
Abstracts Neo4J Lucene capabilities
Spring Data Neo4J - TraversalRepository
Encapsulate Neo4J traversals
Spring Data Neo4J repositories
Write less, do more
public interface BranchRepository extends GraphRepository<Branch> {
Iterable<Branch> findByNameLike(String name);
@Query("MATCH (project:PROJECT)-[b:HAS_BRANCH]->(commit:COMMIT) RETURN b")
Page<Branch> lookMaIveGotPages();
Branch findByNameAndCommitIdentifierLike(String name, String commit);
}
Spring Data Neo4J repositories
Cypher DSL via CypherDSLRepository
Execute query = start(lookup("company", "Company", "name", param("name"))).
match(path().from("company").in("WORKS_AT").to("person")).
returns(identifier("person"));
Page<Person> result = repo.query(
query , map("name","Neo4j"), new PageRequest(1,10)
);
Spring Data Neo4J entities
Nodes
@NodeEntitypublic class Person {
@GraphIdprivate Long id;@Indexed(indexName="people-search", 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 entities
Relationships
@RelationshipEntity(type="FRIEND_OF")public class Friendship {
@StartNodeprivate Person person;@EndNodeprivate Dog humansBestFriend;@GraphProperty /* optional here ;-) */private Date since;/** * moaaaaar properties */
}
Spring Data Neo4J template
Pre-shaved yaks!
public class PersonRepositoryImpl extends CustomPersonRepository {@Autowired /* [SPRING ANNOTATION] */private Neo4jTemplate template;
public Iterable<Person> findAllByNameCustom(String name) {Index<Node> personFulltextIndex =
template.getIndex("people-search", Person.class);personFulltextIndex.query("name", format("*%s*", name));// [...]
}}
and moaaar: createNode, projectTo...
And so much more...
Geospatial queries
Cross-store support
Dynamic relationships
“Advanced” mapping
<dependency>
<groupId>org.springframework.
data</groupId>
<artifactId>spring-data-neo4j</artifactId>
<version>2.3.1.RELEASE</version>
</dependency>
And so much more...
Geospatial queries
Cross-store support
QueryDSL integration
“Advanced” mapping
<dependency>
<groupId>org.springframework.
data</groupId>
<artifactId>spring-data-neo4j</artifactId>
<version>2.3.1.RELEASE</version>
</dependency>
Going further
Experiment
http://projects.spring.io/spring-data-neo4j/
Discuss
https://groups.google.com/forum/#!forum/neo4jfr
Share
http://www.meetup.com/graphdb-france/
Calendar
ConferenceOctober / http://tinyurl.com/soft-shake-neo4j
Traininghttp://www.lateral-thoughts.com/formation-neo4j
BBL : just ping me!http://www.brownbaglunch.fr/baggers.html#Florent_Biville
?