#Neo4J : mes premiers pas ##Au départ ! Neo4J est une base de données NoSQL orientée graphes. Je me suis livré à quelques essais, je vous livre ici le mode d'emploi des premiers pas afin de mettre en place très vite une preuve de concept. ##Initier le projet Le plus simple est de débuter par une version "embeded", donc avec une base de données intégrée au projet, sans serveur séparé, à la mode SQLite. Dans ce cas, il est seulement nécessaire de spécifier la dépendance idoine dans le projet :
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j</artifactId>
<version>1.7.2</version>
</dependency>
Cela suffit pour descendre les librairies nécessaires dans le projet Java. Nous allons découper notre preuve de concept en 3 phases:
public static void main(String[] args) {
TrialNeo4j trial = new TrialNeo4j();
trial.initDb();
trial.feedDb();
trial.exploreDb();
}
Occupons-nous maintenant de construire la base ! ##Construire la base
void initDb(){
graphDb = new GraphDatabaseFactory().newEmbeddedDatabase( DB_PATH );
registerShutdownHook( graphDb );
}
Je passe sur les imports nécessaires (Eclipse vous les indiquera) ainsi que sur le shutdown qui ne nous concerne pas pour l'instant. Pour commencer nous créons une base de données toute neuve. DB_PATH
indique un chemin vers un répertoire qui sera créé s'il n'existe pas et doit de toute manière être vide, sinon une exception nous attend au tournant. J'ai bien évidemment déclaré les attributs nécessaires.
private static String DB_PATH = "target/trial-db";
private GraphDatabaseService graphDb;
Nous nous occuperons de l'ouverture d'une base existante plus tard. Tout d'abord nous allons peupler cette base vide. ##Créer des éléments dans Neo4J Neo4J est une base de données orientée graphe, sans schémas. Il n'y a donc pas de déclarations de structure à faire, il suffit de créer les éléments directement. Il n'y en a que 2 types:
- Les noeuds
- Les relations Les relations sont typées, ce qui n'est (hélas) pas le cas des noeuds. Qu'à cela ne tienne, nous allons simplement créer un enum "NodeType" dont nous associeront la valeur à une propriété. Pour rester dans mon domaine d'activité, je vais faire un bout de modélisation de la CIM10. Commençons par créer un nom "source" de la classification :
void feedDb(){
Transaction tx = graphDb.beginTx();
try
{
Node oms = graphDb.createNode();
oms.setProperty("type", NodeType.CIM10_ORIGIN);
oms.setProperty("origin", "OMS");
...
}
finally
{
tx.finish();
}
Les créations d'éléments doivent être encadrés dans une transaction. L'instance de GraphDatabaseService
sert de Factory à la création des noeuds. Les propriétés peuvent être librement affectées à un noeud sous forme de "clé - valeur" sans que les définitions de ces propriétés aient été définies au préalable.
Comme je vais créer beaucoup de noeuds "CIM10", j'écris un petit builder dédié à cela :
Node createCim10Node(String code, String labelFr, Node origin, Node cimClass){
Node firstNode = graphDb.createNode();
firstNode.setProperty("type", NodeType.CIM10);
firstNode.setProperty("code", code);
createLabel(firstNode, labelFr, "fr");
firstNode.createRelationshipTo(origin, RelTypes.ORIGIN);
firstNode.createRelationshipTo(cimClass, RelTypes.CLASS);
return firstNode;
}
J'ai aussi séparé le noeud "CIM10 de son libellé et créé un builder pour ce dernier. Je ne vous assène pas le code, c'est le même genre. On voit ici la création de relations entre noeuds avec la méthode createRelationshipTo
qui prend en paramètre un noeud cible et un type de relation. Il s'agit d'un énuméré qui doit être un sous-type de RelationshipType
. Voici ce qu'il en est pour moi:
private static enum RelTypes implements RelationshipType
{
LABEL,
CLASS,
PARENT,
ORIGIN
}
La méthode createLabel
qui associe un label à un noeud (car je gère l'internationalisation) est de la même eau:
void createLabel(Node nodeToLabel, String label, String lang) {
Node labelNode = graphDb.createNode();
labelNode.setProperty("type", NodeType.LABEL);
labelNode.setProperty("lang", lang);
nodeToLabel.createRelationshipTo(labelNode, RelTypes.LABEL);
}
Il est temps de créer les autres noeuds pour utiliser effectivement tout ça:
Node cimClass = graphDb.createNode();
cimClass.setProperty("type", NodeTypes.CIM10_CLASS);
cimClass.setProperty("codeRange", "C00-C14");
createLabel(cimClass, "Tumeurs malignes, lèvre, cavité buccale et pharynx", "fr");
Node firstNode = createCim10Node("C04", "Tumeur maligne de la langue", oms, cimClass);
Node cimChild1 = createCim10Node("C04.0", "Plancher antérieur de la bouche", oms, cimClass);
cimChild1.createRelationshipTo(firstNode, RelTypes.PARENT);
Node cimChild2 = createCim10Node("C04.1", "Plancher latéral de la bouche", oms, cimClass);
cimChild2.createRelationshipTo(firstNode, RelTypes.PARENT);
Ce code prend place dans la transaction que nous avons ouverte précédemment. Je viens de créer une "classe CIM" à laquelle tous les noeuds de ma classification vont se rattacher. Cette classification est composée d'un noeud parent firstNode
et de deux noeuds enfants : cimChild1
et cimChild2
. Un petit dessin vaut mieux qu'un long discours.
Nous allons maintenant naviguer sur ces relations. Mais avant cela, il nous allons ouvrir notre base non plus en création, mais en lecture/écriture d'une base déjà existante ###Naviguer sur les noeuds