Skip to content

Instantly share code, notes, and snippets.

@addinquy
Last active June 28, 2019 13:05
Show Gist options
  • Save addinquy/3772050 to your computer and use it in GitHub Desktop.
Save addinquy/3772050 to your computer and use it in GitHub Desktop.
Neo4J pour les nuls

#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.

neo4j-cim10

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment