Comment (ne pas réussir à) modéliser ses data dans Elasticsearch

Comment (ne pas réussir à) modéliser ses data dans Elasticsearch

Présentation faite au BreizhCamp 2015 sur la modélisation des données dans Elasticsearch.

Bc34f46fdfa199da05a78f26584ecec3?s=128

Bruno Bonnin

June 25, 2015
Tweet

Transcript

  1. BreizhCamp 2015 #BzhCmp BreizhCamp 2015 #BzhCmp Comment (ne pas réussir

    à) modéliser ses data dans Elasticsearch! Bruno Bonnin - @_bruno_b_
  2. $ whoami Bruno Bonnin > Plus de 15 ans dans

    les télécoms (dev, archi, pompier) > Aujourd’hui @_bruno_b_ github.com/bbonnin
  3. Il était une fois un assureur…

  4. Le contexte Contrats Personnes TEL LDAP Copie entre systèmes Navigation

    entre clients
  5. Le puits de données avec Elastic ! Contrats Personnes TEL

    LDAP Search-based Apps Consultation uniquement, les systèmes d’origine restent maîtres de la donnée
  6. ELK : La triplette de la mort !

  7. None
  8. Quelques questions à se poser… • Les usages ? Partiellement

    connus… • Vue 360° du sociétaire • Recherche sur des référentiels • Ça arrive au fur et à mesure… • Quelles données ? Toutes (ou presque) ! • De multiple sources de données, complexes à croiser • Des contraintes techniques ? Système des mises à jour imposé ! • Messages générés à partir des updates issus des différents système, sans garanti d’ordre • Problème potentiel de mises à jour des documents dans ES (cas nested : conteneur de la donnée pas encore présente dans le puits)
  9. Alimentation Du Puits de données Focus : mises à jour

    du puits Contrats Personnes TEL LDAP JMS Fil de l’eau Batch
  10. Quel modèle pour elastic ? Sinistres TEL Contrats Personnes ?

  11. None
  12. « La brute » ? Un seul type de document

    ! { "nom" : "Haddock", "prenom" : "Archibald", "age" : 56, "contrats" : [ { "formule" : "assur_auto", "bien" : { "immatriculation" : "1-AAA-99", "modele" : "peugeot 504", } "garanties" : [ ... ], }, { … } ], "sinistres" : [ { … }, { … } ] } Doc Societaire
  13. « La brute » ? Un seul type de document

    ! { "nom" : "Haddock", "prenom" : "Archibald", "age" : 56, "contrats" : [ { "formule" : "assur_auto", "bien" : { "immatriculation" : "1-AAA-99", "modele" : "peugeot 504", } "garanties" : [ ... ], }, { … } ], "sinistres" : [ { … }, { … } ] } Doc Societaire Personnes Contrats Sinistres
  14. « La brute » ? Un seul type de document

    ! { "query" : { "nested" : { "path" : "contrats", "query" : { "bool" : { "must" : [ { "match" : { "contrats.formule" : “assur_auto" }, "match" : { "contrats.bien.modele" : "peugeot 504" } ] } } } } } } { "societaire" : { "properties" : { "contrats" : { "type" : "nested ", "properties" : { "formule" : { "type" : "string“ }, "bien" : { … }, … } }, "sinistres" : { "type" : "nested" } } } } Mapping Query
  15. « La brute » ? Un seul type de document

    ! Avantage(s) : • Avec une seule requête, on récupère l’ensemble des données d’un sociétaire • Requêtes complexes sur les sous-documents Désavantage(s) : • La mise à jour ! • Temps de ré-indexation • Complexité (quid des messages concernant un sous- partie sans le document conteneur ?) • Vue orientée « sociétaire » : quid des use cases orientés « contrat » ?
  16. « La brute » ? Un seul type de document

    ! Avantage(s) : • Avec une seule requête, on récupère l’ensemble des données d’un sociétaire • Requêtes complexes sur les sous-documents Désavantage(s) : • La mise à jour ! • Temps de ré-indexation • Complexité (quid des messages concernant un sous- partie sans le document conteneur ?) • Vue orientée « sociétaire » : quid des use cases orientés « contrat » ?
  17. « Le truand » ? Un doc par objet source

    { "num_soc" : "1234", "nom" : "Haddock", "prenom" : "Archibald", "age" : 56 } Sociétaire { "num_contrat" : "6789", "type" : "auto", "immatriculation" : "1-AAA-99", "modele" : "peugeot 504", "num_soc" : "1234" } Contrat { "num_contrat" : "6789", … } Garantie { "num_soc" : "1234", … } Sinistre
  18. « Le truand » ? Un doc par objet source

    { "num_soc" : "1234", "nom" : "Haddock", "prenom" : "Archibald", "age" : 56 } Sociétaire { "num_contrat" : "6789", "type" : "auto", "immatriculation" : "1-AAA-99", "modele" : "peugeot 504", "num_soc" : "1234" } Contrat { "num_contrat" : "6789", … } Garantie Personne Contrats Contrats { "num_soc" : "1234", … } Sinistre Sinistres
  19. « Le truand » ? Un doc par objet source

    GET /societaire,contrats/_search { "query" : { “term" : { “num_soc" : “1234" } } } Query … { "_index" : “assureur", "_type" : "contrats", "_id" : "2045", "_score" : 4.4011974, "_source“ : { "num_contrat" : "2045", "num_soc" : “1234", "type" : "assur_maison", "bien" : { "type" : "chateau", "adresse" : “moulinsart" } } } ] } "hits" : { "total" : 2, "max_score" : 4.417726, "hits" : [ { "_index" : “assureur", "_type" : "societaire", "_id" : "45", "_score" : 4.417726, "_source“ : { "num_soc" : “1234", "nom" : "haddock" } }, … Result Recherche sur 2 types de docs en utilisant le champ commun « num_soc »
  20. « Le truand » ? Un doc par objet source

    Avantage(s) : • Facile à mettre à jour (1 type de doc correspond à 1 type de message) Désavantage(s) : • Requêtage : devient vite complexe pour avoir une information complète • Multiplication des requêtes côté client pour reconstituer le modèle
  21. « Le truand » ? Un doc par objet source

    Avantage(s) : • Facile à mettre à jour (1 type de doc correspond à 1 type de message) Désavantage(s) : • Requêtage : devient vite complexe pour avoir une information complète • Multiplication des requêtes côté client pour reconstituer le modèle
  22. « Le bon » ? Un mix nested et parent/child

    { "num_soc" : "1234", "nom" : "Haddock", "prenom" : "Archibald", "age" : 56 } Sociétaire { "num_contrat" : "6789", "type" : "maison", "bien" : { "type" : "chateau", "localisation" : "moulinsart" } "garanties" : [ {…}, {…} ] } Contrat
  23. « Le bon » ? Un mix nested et parent/child

    { "num_soc" : "1234", "nom" : "Haddock", "prenom" : "Archibald", "age" : 56 } Sociétaire { "num_contrat" : "6789", "type" : "maison", "bien" : { "type" : "chateau", "localisation" : "moulinsart" } "garanties" : [ {…}, {…} ] } Contrat Personnes Contrats parent=1234 Relation parent/child entre des docs liés mais vivant indépendamment Contrat complet avec nested docs car forte dépendance
  24. « Le bon » ? Un mix nested et parent/child

    { "societaire" : { … }, "contrat" : { “_parent” : { "type" : “societaire“ }, "properties" : { “bien" : { "type" : "nested" }, “garanties" : { "type" : "nested" } } Mapping PUT /contrat/6789?parent=1234 { "num_soc" : "1234", "type" : "assur_maison", "bien" : { "type" : "chateau", "adresse" : "moulinsart", }, "garanties" : [] } Indexation Déclaration du parent
  25. « Le bon » ? Un mix nested et parent/child

    GET /societaire/_search { “query” : { “has_child" : { “type” : “contrat”, "query" : { "match" : { “bien.adresse" : “moulinsart" } } }, "inner_hits" : {} } } } Query … "inner_hits" : { "contrats" : { "hits" : { "total" : 1, "max_score" : 3.4336133, "hits" : [ { "_index" : “assureur", "_type" : "contrat", "_id" : “6789", "_score" : 3.4336133, "_source“ : { "num_contrat" : “6789", "num_soc" : “1234", "type" : "assur_maison", "bien" : { "type" : "chateau", "adresse" : "moulinsart" } } } ] { "_index" : “assureur", "_type" : "societaire", "_id" : “1234", "_score" : 1.0, "_source“ : { "num_soc" : “1234", "nom" : "haddock" }, … Result « inner_hits » (new 1.5) : permet d’avoir les contrats en plus des sociétaires dans le résultat
  26. « Le bon » ? Un mix nested et parent/child

    Avantage(s) : • Modèle permettant de répondre à la plupart des usages (orienté sociétaire ou contrat) • Séparation de documents ayant des cycles de vie différents • Avec inner_hits, capacité à retrouver des documents liés entre eux facilement Désavantage(s) : • Requêtes plus lentes pour les docs liés par une lien parent/enfant • Elastic met en mémoire la table des liens
  27. None
  28. Cluster Elastic Architecture Nœud sans data Nœud data 1 Nœud

    data 2 Shield Marvel Alim puits de données 1 Alim puits de données 2 JMS … Taille des index (mesure PoC) : 400 Go
  29. En résumé Penser « usages » est primordial ! Utiliser

    les nested documents pour des données ayant un lien fort, avec le même cycle de vie • Ne pas hésiter à dupliquer Utiliser les liens parents/enfants sur les documents pouvant vivre indépendamment les uns des autres • Requêtes avec « inner_hits » Tenir compte des contraintes techniques de votre env
  30. MERCI ! Crédit photos : https://www.flickr.com/photos/hoyvinmayvin