Neo4j en pratique: quand le graphe bat une BD classique
Neo4j est une base de donnees graphe ou les donnees vivent comme noeuds et relations, pas comme lignes de tables. Une BD relationnelle classique (PostgreSQL, MySQL) couvre tres bien transactions, rapports et CRUD. Mais quand la valeur produit reside dans les chemins, chaines et liens multi-sauts, le SQL avec JOIN et CTE recursifs devient vite lourd et fragile. Ci-dessous - des signaux pratiques pour savoir quand Neo4j gagne face a une BD "classique", et quand le graphe est encore premature.
- Graphe - noeuds (entites) + aretes (relations typees) + proprietes
- Force de Neo4j - parcours de relations a profondeur variable
- Faiblesse du SQL - JOIN profonds, "amis d'amis", chaines fraude/acces
- Pas un remplacement - CRUD transactionnel, stock, analytique classique
- Regle - choisissez Neo4j quand la question ressemble a "via qui / via quoi / en N hops"
En quoi un graphe differe des tables
Dans PostgreSQL vous modelisez les relations avec des foreign keys et des tables de liaison (user_roles, follows, order_items). Une requete a profondeur fixe reste lisible. Une requete du type "trouve tous les noeuds dans un rayon de 3-5 hops avec filtres par type de relation" devient un CTE recursif ou de nombreux JOIN - et le plan d'execution croit avec la profondeur.
Dans Neo4j une relation est first-class. Le modele se rapproche de la facon dont les gens decrivent le domaine:
(:Person)-[:WORKS_AT]->(:Company)(:Account)-[:TRANSFERED_TO]->(:Account)(:User)-[:HAS_ROLE]->(:Role)-[:ALLOWS]->(:Permission)
Une requete Cypher decrit un motif, pas un "collage de tables". C'est utile quand la profondeur du chemin est inconnue a l'avance ou change souvent.
Quand Neo4j bat une BD classique
Choisissez un graphe si le cahier des charges contient regulierement:
- Parcours a profondeur variable - "amis d'amis", chaine d'approvisionnement, chemin jusqu'au proprietaire racine.
- Pattern matching sur les relations - trouver des sous-graphes du type "A lie a B via C sous la condition D".
- Recommandations et entites similaires via le graphe - pas seulement par texte, mais par voisins communs et chemins.
- Fraude et risque - anneaux, appareils partages, chemins courts entre comptes "etrangers".
- Droits et dependances - qui accede a quoi via roles, groupes et heritage.
- Knowledge graph - produits, documents, personnes, systemes et relations explicites entre eux.
Signaux que le SQL "fait deja mal":
- les CTE recursifs s'allongent a chaque release;
- l'equipe craint de changer le schema de relations;
- la latence augmente justement sur les JOIN profonds, pas sur les SELECT simples;
- le metier demande "montre la chaine", pas "donne la ligne par id".
Exemple pratique: chemin et voisins communs
Supposons qu'il faille trouver des entreprises liees a une personne en au plus deux etapes, filtrees par type de relation.
MATCH path = (p:Person {id: $personId})-[:WORKS_AT|KNOWS*1..2]-(c:Company)
WHERE c.country = $country
RETURN DISTINCT c.name AS company, length(path) AS hops
ORDER BY hops, company
LIMIT 50;
Le meme sens en SQL demande souvent de la recursion, une deduplication soigneuse et des limites de profondeur. Dans le graphe la formulation est plus proche de la question metier.
Exemple "voisins communs" pour les recommandations:
MATCH (u:User {id: $userId})-[:BOUGHT]->(:Product)<-[:BOUGHT]-(other:User)
WHERE u <> other
WITH other, count(*) AS shared
ORDER BY shared DESC
LIMIT 20
RETURN other.id, shared;
Quand une BD classique reste meilleure
Neo4j n'est pas un remplacement universel de PostgreSQL.
Gardez une BD relationnelle (ou commencez par elle) si:
- le flux principal est CRUD, commandes, paiements, stock, billing;
- les relations ont une profondeur fixe (1-2 JOIN) et restent stables pendant des annees;
- vous avez besoin d'agregats lourds, de fenetres et de reporting BI;
- l'equipe est forte en SQL et les requetes graphe sont rares;
- la logique "reseau" est petite et un CTE suffit sans douleur.
Erreur typique: tout migrer vers Neo4j "parce que les graphes sont a la mode". Vous gagnez de l'ops inutile et un mauvais fit pour le coeur transactionnel.
Hybride: PostgreSQL + Neo4j
En pratique une separation fonctionne souvent:
| Couche | Ou stocker | Pourquoi |
|---|---|---|
| Commandes, utilisateurs, paiements | PostgreSQL / MySQL | Transactions, integrite, rapports |
| Relations, chemins, roles, dependances | Neo4j | Traversal et pattern match |
| Recherche semantique de texte | Store vectoriel | RAG / semantic search |
Source de verite pour l'argent et les statuts - la BD relationnelle. Synchronisez le graphe via evenements (outbox, CDC, file) ou par lots. Ainsi vous ne dupliquez pas le billing dans Neo4j et ne construisez pas un graphe de fraude uniquement avec des JOIN.
Comment valider l'hypothese en 1-2 semaines
- Listez 15-20 vraies questions d'utilisateurs/analystes.
- Marquez combien portent sur chemins, hops et "via qui".
- Si cette part depasse ~30-40%, construisez un pilote Neo4j sur un sous-graphe reduit.
- Comparez avec SQL: lisibilite, latence p95, cout des changements de schema.
- Estimez le cout de synchronisation avec la BD principale.
Si le pilote ne gagne pas en latence/clarte - restez sur PostgreSQL. Un graphe doit resoudre une douleur, pas decorer l'architecture.
Conclusion
Neo4j bat une BD classique la ou le produit pense en relations: chaines, roles, dependances, fraude, knowledge graph, recommandations par graphe. Une BD classique gagne la ou le coeur est transactions, JOIN fixes et rapports. Souvent l'optimum est un hybride: SQL pour les faits et l'argent, graphe pour la structure et les chemins.
Si vous devez decider si les relations doivent aller dans Neo4j, ou concevoir un pilote pour votre domaine - contactez-moi.
Questions frequentes
En quoi Neo4j est-il fondamentalement meilleur que PostgreSQL pour les relations?
Vitesse et clarte du parcours a profondeur variable. Dans un graphe, les aretes sont indexees comme relations, pas reconstruites a chaque fois via des JOIN de tables. Pour 1-2 JOIN fixes PostgreSQL suffit souvent; pour "N hops avec filtres par type de relation" Neo4j est en general plus simple et plus stable.
Les CTE recursifs de PostgreSQL peuvent-ils remplacer Neo4j?
Parfois oui, au debut. Si la profondeur est faible, le graphe modere et les requetes peu nombreuses - les CTE marchent. Quand profondeur, branchement et nombre de requetes de motifs croissent, les CTE deviennent durs a maintenir et coutent cher dans le plan d'execution.
Faut-il migrer tout le produit vers Neo4j?
Non. Deplacez la couche ou les relations sont de la valeur produit. Laissez commandes, paiements, stock et CRUD classique dans la BD relationnelle. Sinon vous obtenez un mauvais fit et une complexite ops inutile.
Cypher est-il plus difficile que SQL?
Un autre modele mental, pas forcement plus difficile. Pour chemins et motifs Cypher est plus court et plus lisible. Pour agregats, reporting et fonctions fenetre SQL est plus familier. L'equipe a besoin d'un court onboarding et de 5-10 requetes de reference du domaine.
Comment commencer l'adoption de Neo4j dans un projet existant?
Par un pilote sur un scenario: par exemple graphe d'acces, anneaux de fraude ou carte de dependances de services. Definissez la source de verite, le mode de sync et 10 questions de controle. Ce n'est qu'apres mesure de latence et hit-rate que vous elargissez a d'autres domaines.