Optimisez vos imports de
 données avec Migrate
Qui suis-je ?

           Matthieu Guillermin
             •    Consultant chez Clever Age
             •    Java, PHP, Symfony, Play!,... et ... Drupal


                     @mguillermin


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   2
Matthieu Guillermin - Mai 2012
Agenda

        •     Contexte
        •     Solutions d’import de données dans Drupal
        •     Anatomie d’une tâche Migrate
        •     Gestion des références entre contenus
        •     Stratégies d’optimisation


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   3
Matthieu Guillermin - Mai 2012
Imports de données


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   4
Matthieu Guillermin - Mai 2012
Imports de données

        •     Problème récurrent
             •    Récupération de contenu initial
             •    Affichage de données depuis sources externes
             •    Agrégation de données
             •    ...


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   5
Matthieu Guillermin - Mai 2012
Imports de données

        •     Problématiques variées
             •    Sources : BDD, fichiers, flux,...
             •    Structures de donnée : plat, relationnel,...
             •    Fréquences d’imports : one-shot, quotidient,...
             •    Cibles : Nodes, Files, Users, Taxonomy,...


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate    6
Matthieu Guillermin - Mai 2012
Solutions d’import de
             données dans Drupal


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   7
Matthieu Guillermin - Mai 2012
« A la main »
        •     Transfert direct vers la base
             •    Via des scripts
             •    En utilisant un ETL
        •     Schéma cible difficile à appréhender
             •    Encore + depuis Drupal 7
             •    Risque d’erreurs important


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   8
Matthieu Guillermin - Mai 2012
« A la main »
        •     En utilisant l’API Drupal pour enregistrer les
              données
             •    Développement d’un module
             •    Implémentation de la lecture des données
             •    Construction de la structure du node
             •    Utilisation de node_save() pour
                  l’enregistrement

Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   9
Matthieu Guillermin - Mai 2012
« A la main »
        •     Les +
             •    Souplesse totale sur la source et les
                  traitements
        •     Les -
             •    Beaucoup de travail
             •    On va « réinventer la roue »
             •    Difficile de construire la structure « node »

Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   10
Matthieu Guillermin - Mai 2012
Feeds

        •     Module « historique » pour l’import de
              données
        •     Au départ, plutôt dédié aux flux XML (RSS)
        •     Configuration UI + API
        •     Connecteurs disponibles : XML, CSV, LDAP,...


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   11
Matthieu Guillermin - Mai 2012
Feeds
           •     Les +
               •     Rapide à mettre en place
               •     Configuration via l’interface
               •     Connecteurs disponibles
           •     Les -
               •     Peu adapté aux gros volumes de données
               •     Difficile de gérer les cas « particuliers »
               •     Références entre les contenus
Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   12
Matthieu Guillermin - Mai 2012
Migrate
        •     Module dédié à l’import de données
        •     Interface graphique minimale
        •     Nécessite de « coder » les imports
        •     Fournit des outils clés en main (lancement de
              tâches, ...)
        •     Peut faire peur de prime abord


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   13
Matthieu Guillermin - Mai 2012
Migrate
        •     Les +
             •    Connecteurs fournis
             •    Performances sur de gros volumes
             •    Gestion des références entre contenus
        •     Les -
             •    Nécessite d’écrire du code
                 • ça pourrait être un + !
Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   14
Matthieu Guillermin - Mai 2012
En résumé
        •     Feeds
             •    Si vous voulez une interface simple
             •    Si il suffit à votre besoin
             •    Et si vous aimez cliquer
        •     Sinon, Migrate
             •    Pas si compliqué que ça


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   15
Matthieu Guillermin - Mai 2012
Anatomie d’une tâche
                  Migrate


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   16
Matthieu Guillermin - Mai 2012
Source
        •     Gère le requêtage des données
             •    SQL : MySQL, Oracle, MSSQL,..
             •    Fichiers : CSV, XML, ...
             •    Fournit une série d’enregistrements
                 • Avec les valeurs des champs
        •     S’occupe du parcours des données
        •     Extensible en cas de besoin

Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   17
Matthieu Guillermin - Mai 2012
Source
   $query = Database::getConnection('myDb', 'myDbKey')
       ->select('article', 'a');
   $query->innerJoin(‘article_category’, ‘ac’,
       ‘a.category_id = ac.id’);

   $query->fields(‘a’, ‘id’);
   $query->fields(‘a’, ‘title’);
   $query->fields(‘a’, ‘content’);
   $query->fields(‘ac’, ‘name’, ‘cat_name’);

   $this->source = new MigrateSourceSQL($query, array(),
       NULL, array('map_joinable' => FALSE));




Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   18
Matthieu Guillermin - Mai 2012
Source
   $this->source = new MigrateSourceCSV($source_file,
     $this->csvcolumns(), array('header_rows' => 1),
     array());

   function csvcolumns() {
     $columns[0] = array('title', 'Title');
     $columns[2] = array('desc', 'Description');
     return $columns;
   }




Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   19
Matthieu Guillermin - Mai 2012
Source

   $items_url = $xml_folder . 'positions.xml';
   $item_xpath = '/producers/producer';
   $item_ID_xpath = 'sourceid';

   $this->source = new MigrateSourceXML($items_url,
     $item_xpath, $item_ID_xpath, $fields);




Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   20
Matthieu Guillermin - Mai 2012
Destination
        •     Gère l’enregistrement des données
             •    Types fournis par Migrate :
                 • User, Role, Node, Comment, Term, File,...
             •    Utilise l’API pour enregistrer : node_save,
                  user_save(),...
        •     Extensible
             •    on peut créer ses propres types de
                  destinations
Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   21
Matthieu Guillermin - Mai 2012
Destination
   // Node
   $this->destination = new MigrateDestinationNode(
       'article', array('text_format' => 'full_html'));


   // Taxonomy
   $this->destination = new MigrateDestinationTerm(
       ‘voc_name’);


   // User
   $this->destination = new MigrateDestinationUser();




Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   22
Matthieu Guillermin - Mai 2012
Mapping
        •     Associations champs
             •    Source => Destination
        •     Peuvent être simples ou + complexes
             •    Transformation de données
             •    Conversion de formats
             •    ...


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   23
Matthieu Guillermin - Mai 2012
Mapping

           SRC                                                      DEST
        SRC_ID                                                     DEST_ID
         SRC_1                                    Transfo.         DEST_1
         SRC_2                                                     DEST_2
         SRC_3                                    Transfo.         DEST_3



Drupal Camp Lyon - Optimisez vos imports de données avec Migrate             24
Matthieu Guillermin - Mai 2012
Mapping
        •     Transformations de données
             •    Chaîne ➞ tableau (explode)
             •    Appel de « Callbacks »
        •     Arguments
             •    A utiliser suivant les types de champs
             •    cf les « Migrate*FieldHandler »


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   25
Matthieu Guillermin - Mai 2012
Mapping
   // Default value
   $this->addFieldMapping('language', 'lang')
     ->defaultValue('fr');

   // Multiple
   $this->addFieldMapping('field_auteur', 'auteurs')
     ->separator(',');

   // Callbacks
   $this->addFieldMapping('title', 'titre')
     ->callbacks(
       'strip_tags',
       array($this, 'trimTitle'),
       array($this, 'convertToUtf8')
     );




Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   26
Matthieu Guillermin - Mai 2012
Mapping
        •     « Sous le capot »
             •    les FieldHandlers s’occupent de
                  convertir les valeurs
             •    Construction des structures en fonction des
                  types de champs
             •    Utilise les arguments pour savoir comment les
                  générer


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   27
Matthieu Guillermin - Mai 2012
FieldHandlers
   // Before
   string(2) "C1"

   // After
   ["field_numero"]=>
     array(1) {
       ["und"]=>
       array(1) {
         [0]=>
         array(3) {
            ["value_format"]=>
            string(10) "plain_text"
            ["format"]=>
            string(10) "plain_text"
            ["value"]=>
            string(2) "C1"
         }
       }
     }


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   28
Matthieu Guillermin - Mai 2012
Mapping
   // Arguments Date
   $date_args =
     DateMigrateFieldHandler::arguments('Europe/Paris');
   $this->addFieldMapping('field_pub_date', 'pub')
     ->arguments($date_args);

   // Arguments Term Reference
   $this->addFieldMapping('field_categorie', 'categorie')
     ->arguments(array(
       'source_type' => 'tname',
       'create_term' => TRUE
     ));




Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   29
Matthieu Guillermin - Mai 2012
Map

        •     Correspondance entre ID source et ID
              destination
             •    Stockée dans une table dédiée
             •    Permet de relancer une tâche en « update »
             •    Permet les « rollbacks »
             •    Permet les références entre contenus


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   30
Matthieu Guillermin - Mai 2012
Map
                                                       MAP
                                             ID Src 1         ID Dest 1

                                             ID Src 2         ID Dest 2


           SRC                                                             DEST
        SRC_ID                                                            DEST_ID
         SRC_1                                    Transfo.                DEST_1
         SRC_2                                                            DEST_2
         SRC_3                                    Transfo.                DEST_3

Drupal Camp Lyon - Optimisez vos imports de données avec Migrate                    31
Matthieu Guillermin - Mai 2012
Map

   $this->map = new MigrateSQLMap($this->machineName,
      array(
         'id' => array(
           'type' => 'int',
           'unsigned' => TRUE,
           'description' => 'Content ID',
         )
      ),
      MigrateDestinationNode::getKeySchema()
   );




Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   32
Matthieu Guillermin - Mai 2012
Anatomie d’une tâche

        •     En résumé :
             •    Source
             •    Destination
             •    Mapping
             •    Map


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   33
Matthieu Guillermin - Mai 2012
Migration

        •     1 Migration = 1 Classe PHP
             •    Doit étendre Migration

        •     Configuration de
             •    Source, Destination, Field Mapping, Map
             •    Effectuée dans __construct()


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   34
Matthieu Guillermin - Mai 2012
Migration
        •     Offre des points d’entrée pour
             •    Altérer les données en lecture
                 • prepareRow($row)
             •    Altérer les entités en écriture
                 • prepare($entity, $row)
        •     Possibilité d’héritage
             •    Mutualisation de configuration

Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   35
Matthieu Guillermin - Mai 2012
Lancement des tâches

        •     Pour lancer les tâches
             •    Ligne de commande
                 • Drush
             •    Interface graphique
                 • Disponible dans le BackOffice


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   36
Matthieu Guillermin - Mai 2012
Lancement des tâches

        •     Drush
             •    Différentes commandes : mi, ms, mr, mrs
             •    Paramètres intéressants :
                 • «limit» : permet de limiter le nombre d’éléments
                       à importer (ou le temps d’import)
                 • «feedback» : notifications de l’avancement


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate      37
Matthieu Guillermin - Mai 2012
Lancement tâches
   $ drush ms
    Name                         Total    Imported      Unimported   Status   Last imported
    LyonMetroLigneTypes          4        4             0            Idle     2012-05-23 13:49:35
    LyonMetroLignes              154      154           0            Idle     2012-05-23 14:08:29
    LyonMetroArrets              4036     4036          0            Idle     2012-05-23 13:58:16




   $ drush mi LyonMetroLignes --update --feedback="50 items"
   Processed 50 (0 created, 50 updated, 0 failed, 0 ignored) in 1.4 sec (2156/min) -
     continuing with 'LyonMetroLignes'
   Processed 50 (0 created, 50 updated, 0 failed, 0 ignored) in 1.9 sec (1566/min) -
    continuing with 'LyonMetroLignes'
   Processed 50 (0 created, 50 updated, 0 failed, 0 ignored) in 2.2 sec (1377/min) -
    continuing with 'LyonMetroLignes'
   Processed 4 (0 created, 4 updated, 0 failed, 0 ignored) in 0.3 sec (899/min) - done
    with 'LyonMetroLignes'




Drupal Camp Lyon - Optimisez vos imports de données avec Migrate                                    38
Matthieu Guillermin - Mai 2012
Lancement tâches




Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   39
Matthieu Guillermin - Mai 2012
En pratique...


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   40
Matthieu Guillermin - Mai 2012
Gestion des références
             entre contenus


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   41
Matthieu Guillermin - Mai 2012
Références entre contenus
        •     Prérequis
             •    Mécanisme de dépendances entre tâches
        •     Si B est dépendant de A
             •    La tâche A devra être lancée avant la tâche B


     $this->dependencies = array('MigrationA');




Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   42
Matthieu Guillermin - Mai 2012
Références entre contenus
        •     Tables ‘Map’
             •    Correspondances entre ID src. & dest.
             •    Permet à Migrate de gérer les références
        •     Dans le mapping :

     $this->addFieldMapping('field_a_dest', 'field_a_src')
         ->sourceMigration('MigrationA');




Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   43
Matthieu Guillermin - Mai 2012
Références entre contenus
        •     Lors de l’import de ce champ dans B :
             •    L’Id source va être « converti » en Id
                  Destination en utilisant la table Map de la
                  Migration A

     SELECT destid1                                                /* nid/tid/uid/fid     */
     FROM migrate_map_A                                            /* Map table for ‘A‘   */
     WHERE sourceid1 = :id_src                                     /* id in ‘A’ src table */



             •    C’est l’Id « converti » qui sera enregistré dans
                  le contenu
Drupal Camp Lyon - Optimisez vos imports de données avec Migrate                           44
Matthieu Guillermin - Mai 2012
Références entre contenus
        •     Import de A



        SRC_A                                      MAP_A                 NODE
                                               1023                378
        SRC_ID                                                           NID
                                               1029                379
              ...                                ...               ...    ...




Drupal Camp Lyon - Optimisez vos imports de données avec Migrate                45
Matthieu Guillermin - Mai 2012
Références entre contenus
        •     Import de B

        SRC_B                                          MAP_B             NODE_B
                                               4204                455
        SRC_ID                                 4605                456    NID
                                                 ...               ...
          A_ID                                                            A_REF

                                                   MAP_A
                                               1023                378

                                               1029                379

                                                 ...               ...


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate                  46
Matthieu Guillermin - Mai 2012
En pratique...


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   47
Matthieu Guillermin - Mai 2012
Stratégies
                             d’optimisation


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   48
Matthieu Guillermin - Mai 2012
Requêtage
        •     Comme dans tout import, le requêtage est
              essentiel
             •    Limiter le nombre de requêtes
                 • Eviter de faire une requête pour chaque ligne
                       source
                 • INNER JOIN / LEFT JOIN /...
             •    Optimiser la source (si possible)
                 • ajout d’indexes
                 • configuration DB (innodb_buffer_pool_size,...)
Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   49
Matthieu Guillermin - Mai 2012
Modules « gourmands »

        •     Désactivation de traitements lors de l’import
             •    Pathauto : il faut mieux construire l’url « à la
                  main »
             •    ‘migrate_extras’ fournit un moyen de le
                  désactiver pour une migration donnée



Drupal Camp Lyon - Optimisez vos imports de données avec Migrate     50
Matthieu Guillermin - Mai 2012
Highwater Field
        •     Pour les imports réguliers
             •    N’importer que les données mises à jour
                  depuis le dernier import

             $this->highwaterField = array(
                'name' => 'last_changed',
                'alias' => 'w',
                'type' => 'int',
             );

             $query->orderBy('last_changed');



Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   51
Matthieu Guillermin - Mai 2012
Highwater Field
        •     Avec le Highwater Field
             •    Migrate ajoutera automatiquement une
                  condition sur la requête source
             •    Restriction des enregistrements sources à
                  traiter
             •    Ne fonctionne automatiquement que pour les
                  sources : SQL, Oracle & MSSQL


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   52
Matthieu Guillermin - Mai 2012
preImport()
        •     En cas de structure de base trop « tordue »
             •    On peut être amené à faire une première
                  passe pour charger des éléments en mémoire
             •    Ces éléments seront réinjectés dans chaque
                  contenu cible
             •    Pour cela on peut utilise la méthode
                  preImport()


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   53
Matthieu Guillermin - Mai 2012
// Called once during the migration process
public function preImport()
{
  parent::preImport();
  $query = Database::getConnection('myDB')
    ->select('metas', 'm');
  $query->fields('m', array(
    'id_doc', 'id_meta', 'valeur'));

    /* ... */
    $result = $query->execute();
    while ($row = $result->fetchObject()) {

        if ($row->id_meta == self::ID_META_TITRE) {
          $this->metas[$row->id_doc]['titre'] = $row->valeur;
        }
        if ($row->id_meta == self::ID_META_DATE) {
          $this->metas[$row->id_doc]['date'] = $row->valeur;
        }
    }
}
Drupal Camp Lyon - Optimisez vos imports de données avec Migrate
Matthieu Guillermin - Mai 2012
// Called for each source row
public function prepareRow($row)
{
  if (isset($this->metas[$row->id_doc]['titre'])) {
    $row->titre = $this->metas[$row->id_doc]['titre'];
  }

    if (isset($this->metas[$row->id_doc]['date'])) {
      $row->titre = $this->metas[$row->id_doc]['date'];
    }

    return parent::prepareRow($row);
}




Drupal Camp Lyon - Optimisez vos imports de données avec Migrate
Matthieu Guillermin - Mai 2012
En cas de besoin
        •     Attention à la mémoire
             •    On peut être amené à ajuster la
                  memory_limit
        •     Séparation en 2 migrations
             •    Utilisation de «system of record»
             •    Seuls les champs «mappés» seront écrasés

     $this->systemOfRecord = Migration::DESTINATION;



Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   56
Matthieu Guillermin - Mai 2012
Des questions ?


Drupal Camp Lyon - Optimisez vos imports de données avec Migrate   57
Matthieu Guillermin - Mai 2012
Merci pour votre attention !
      @mguillermin

Optimisez vos imports de données avec Migrate

  • 1.
    Optimisez vos importsde données avec Migrate
  • 2.
    Qui suis-je ? Matthieu Guillermin • Consultant chez Clever Age • Java, PHP, Symfony, Play!,... et ... Drupal @mguillermin Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 2 Matthieu Guillermin - Mai 2012
  • 3.
    Agenda • Contexte • Solutions d’import de données dans Drupal • Anatomie d’une tâche Migrate • Gestion des références entre contenus • Stratégies d’optimisation Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 3 Matthieu Guillermin - Mai 2012
  • 4.
    Imports de données DrupalCamp Lyon - Optimisez vos imports de données avec Migrate 4 Matthieu Guillermin - Mai 2012
  • 5.
    Imports de données • Problème récurrent • Récupération de contenu initial • Affichage de données depuis sources externes • Agrégation de données • ... Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 5 Matthieu Guillermin - Mai 2012
  • 6.
    Imports de données • Problématiques variées • Sources : BDD, fichiers, flux,... • Structures de donnée : plat, relationnel,... • Fréquences d’imports : one-shot, quotidient,... • Cibles : Nodes, Files, Users, Taxonomy,... Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 6 Matthieu Guillermin - Mai 2012
  • 7.
    Solutions d’import de données dans Drupal Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 7 Matthieu Guillermin - Mai 2012
  • 8.
    « A lamain » • Transfert direct vers la base • Via des scripts • En utilisant un ETL • Schéma cible difficile à appréhender • Encore + depuis Drupal 7 • Risque d’erreurs important Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 8 Matthieu Guillermin - Mai 2012
  • 9.
    « A lamain » • En utilisant l’API Drupal pour enregistrer les données • Développement d’un module • Implémentation de la lecture des données • Construction de la structure du node • Utilisation de node_save() pour l’enregistrement Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 9 Matthieu Guillermin - Mai 2012
  • 10.
    « A lamain » • Les + • Souplesse totale sur la source et les traitements • Les - • Beaucoup de travail • On va « réinventer la roue » • Difficile de construire la structure « node » Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 10 Matthieu Guillermin - Mai 2012
  • 11.
    Feeds • Module « historique » pour l’import de données • Au départ, plutôt dédié aux flux XML (RSS) • Configuration UI + API • Connecteurs disponibles : XML, CSV, LDAP,... Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 11 Matthieu Guillermin - Mai 2012
  • 12.
    Feeds • Les + • Rapide à mettre en place • Configuration via l’interface • Connecteurs disponibles • Les - • Peu adapté aux gros volumes de données • Difficile de gérer les cas « particuliers » • Références entre les contenus Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 12 Matthieu Guillermin - Mai 2012
  • 13.
    Migrate • Module dédié à l’import de données • Interface graphique minimale • Nécessite de « coder » les imports • Fournit des outils clés en main (lancement de tâches, ...) • Peut faire peur de prime abord Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 13 Matthieu Guillermin - Mai 2012
  • 14.
    Migrate • Les + • Connecteurs fournis • Performances sur de gros volumes • Gestion des références entre contenus • Les - • Nécessite d’écrire du code • ça pourrait être un + ! Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 14 Matthieu Guillermin - Mai 2012
  • 15.
    En résumé • Feeds • Si vous voulez une interface simple • Si il suffit à votre besoin • Et si vous aimez cliquer • Sinon, Migrate • Pas si compliqué que ça Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 15 Matthieu Guillermin - Mai 2012
  • 16.
    Anatomie d’une tâche Migrate Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 16 Matthieu Guillermin - Mai 2012
  • 17.
    Source • Gère le requêtage des données • SQL : MySQL, Oracle, MSSQL,.. • Fichiers : CSV, XML, ... • Fournit une série d’enregistrements • Avec les valeurs des champs • S’occupe du parcours des données • Extensible en cas de besoin Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 17 Matthieu Guillermin - Mai 2012
  • 18.
    Source $query = Database::getConnection('myDb', 'myDbKey') ->select('article', 'a'); $query->innerJoin(‘article_category’, ‘ac’, ‘a.category_id = ac.id’); $query->fields(‘a’, ‘id’); $query->fields(‘a’, ‘title’); $query->fields(‘a’, ‘content’); $query->fields(‘ac’, ‘name’, ‘cat_name’); $this->source = new MigrateSourceSQL($query, array(), NULL, array('map_joinable' => FALSE)); Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 18 Matthieu Guillermin - Mai 2012
  • 19.
    Source $this->source = new MigrateSourceCSV($source_file, $this->csvcolumns(), array('header_rows' => 1), array()); function csvcolumns() { $columns[0] = array('title', 'Title'); $columns[2] = array('desc', 'Description'); return $columns; } Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 19 Matthieu Guillermin - Mai 2012
  • 20.
    Source $items_url = $xml_folder . 'positions.xml'; $item_xpath = '/producers/producer'; $item_ID_xpath = 'sourceid'; $this->source = new MigrateSourceXML($items_url, $item_xpath, $item_ID_xpath, $fields); Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 20 Matthieu Guillermin - Mai 2012
  • 21.
    Destination • Gère l’enregistrement des données • Types fournis par Migrate : • User, Role, Node, Comment, Term, File,... • Utilise l’API pour enregistrer : node_save, user_save(),... • Extensible • on peut créer ses propres types de destinations Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 21 Matthieu Guillermin - Mai 2012
  • 22.
    Destination // Node $this->destination = new MigrateDestinationNode( 'article', array('text_format' => 'full_html')); // Taxonomy $this->destination = new MigrateDestinationTerm( ‘voc_name’); // User $this->destination = new MigrateDestinationUser(); Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 22 Matthieu Guillermin - Mai 2012
  • 23.
    Mapping • Associations champs • Source => Destination • Peuvent être simples ou + complexes • Transformation de données • Conversion de formats • ... Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 23 Matthieu Guillermin - Mai 2012
  • 24.
    Mapping SRC DEST SRC_ID DEST_ID SRC_1 Transfo. DEST_1 SRC_2 DEST_2 SRC_3 Transfo. DEST_3 Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 24 Matthieu Guillermin - Mai 2012
  • 25.
    Mapping • Transformations de données • Chaîne ➞ tableau (explode) • Appel de « Callbacks » • Arguments • A utiliser suivant les types de champs • cf les « Migrate*FieldHandler » Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 25 Matthieu Guillermin - Mai 2012
  • 26.
    Mapping // Default value $this->addFieldMapping('language', 'lang') ->defaultValue('fr'); // Multiple $this->addFieldMapping('field_auteur', 'auteurs') ->separator(','); // Callbacks $this->addFieldMapping('title', 'titre') ->callbacks( 'strip_tags', array($this, 'trimTitle'), array($this, 'convertToUtf8') ); Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 26 Matthieu Guillermin - Mai 2012
  • 27.
    Mapping • « Sous le capot » • les FieldHandlers s’occupent de convertir les valeurs • Construction des structures en fonction des types de champs • Utilise les arguments pour savoir comment les générer Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 27 Matthieu Guillermin - Mai 2012
  • 28.
    FieldHandlers // Before string(2) "C1" // After ["field_numero"]=> array(1) { ["und"]=> array(1) { [0]=> array(3) { ["value_format"]=> string(10) "plain_text" ["format"]=> string(10) "plain_text" ["value"]=> string(2) "C1" } } } Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 28 Matthieu Guillermin - Mai 2012
  • 29.
    Mapping // Arguments Date $date_args = DateMigrateFieldHandler::arguments('Europe/Paris'); $this->addFieldMapping('field_pub_date', 'pub') ->arguments($date_args); // Arguments Term Reference $this->addFieldMapping('field_categorie', 'categorie') ->arguments(array( 'source_type' => 'tname', 'create_term' => TRUE )); Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 29 Matthieu Guillermin - Mai 2012
  • 30.
    Map • Correspondance entre ID source et ID destination • Stockée dans une table dédiée • Permet de relancer une tâche en « update » • Permet les « rollbacks » • Permet les références entre contenus Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 30 Matthieu Guillermin - Mai 2012
  • 31.
    Map MAP ID Src 1 ID Dest 1 ID Src 2 ID Dest 2 SRC DEST SRC_ID DEST_ID SRC_1 Transfo. DEST_1 SRC_2 DEST_2 SRC_3 Transfo. DEST_3 Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 31 Matthieu Guillermin - Mai 2012
  • 32.
    Map $this->map = new MigrateSQLMap($this->machineName, array( 'id' => array( 'type' => 'int', 'unsigned' => TRUE, 'description' => 'Content ID', ) ), MigrateDestinationNode::getKeySchema() ); Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 32 Matthieu Guillermin - Mai 2012
  • 33.
    Anatomie d’une tâche • En résumé : • Source • Destination • Mapping • Map Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 33 Matthieu Guillermin - Mai 2012
  • 34.
    Migration • 1 Migration = 1 Classe PHP • Doit étendre Migration • Configuration de • Source, Destination, Field Mapping, Map • Effectuée dans __construct() Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 34 Matthieu Guillermin - Mai 2012
  • 35.
    Migration • Offre des points d’entrée pour • Altérer les données en lecture • prepareRow($row) • Altérer les entités en écriture • prepare($entity, $row) • Possibilité d’héritage • Mutualisation de configuration Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 35 Matthieu Guillermin - Mai 2012
  • 36.
    Lancement des tâches • Pour lancer les tâches • Ligne de commande • Drush • Interface graphique • Disponible dans le BackOffice Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 36 Matthieu Guillermin - Mai 2012
  • 37.
    Lancement des tâches • Drush • Différentes commandes : mi, ms, mr, mrs • Paramètres intéressants : • «limit» : permet de limiter le nombre d’éléments à importer (ou le temps d’import) • «feedback» : notifications de l’avancement Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 37 Matthieu Guillermin - Mai 2012
  • 38.
    Lancement tâches $ drush ms Name Total Imported Unimported Status Last imported LyonMetroLigneTypes 4 4 0 Idle 2012-05-23 13:49:35 LyonMetroLignes 154 154 0 Idle 2012-05-23 14:08:29 LyonMetroArrets 4036 4036 0 Idle 2012-05-23 13:58:16 $ drush mi LyonMetroLignes --update --feedback="50 items" Processed 50 (0 created, 50 updated, 0 failed, 0 ignored) in 1.4 sec (2156/min) - continuing with 'LyonMetroLignes' Processed 50 (0 created, 50 updated, 0 failed, 0 ignored) in 1.9 sec (1566/min) - continuing with 'LyonMetroLignes' Processed 50 (0 created, 50 updated, 0 failed, 0 ignored) in 2.2 sec (1377/min) - continuing with 'LyonMetroLignes' Processed 4 (0 created, 4 updated, 0 failed, 0 ignored) in 0.3 sec (899/min) - done with 'LyonMetroLignes' Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 38 Matthieu Guillermin - Mai 2012
  • 39.
    Lancement tâches Drupal CampLyon - Optimisez vos imports de données avec Migrate 39 Matthieu Guillermin - Mai 2012
  • 40.
    En pratique... Drupal CampLyon - Optimisez vos imports de données avec Migrate 40 Matthieu Guillermin - Mai 2012
  • 41.
    Gestion des références entre contenus Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 41 Matthieu Guillermin - Mai 2012
  • 42.
    Références entre contenus • Prérequis • Mécanisme de dépendances entre tâches • Si B est dépendant de A • La tâche A devra être lancée avant la tâche B $this->dependencies = array('MigrationA'); Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 42 Matthieu Guillermin - Mai 2012
  • 43.
    Références entre contenus • Tables ‘Map’ • Correspondances entre ID src. & dest. • Permet à Migrate de gérer les références • Dans le mapping : $this->addFieldMapping('field_a_dest', 'field_a_src') ->sourceMigration('MigrationA'); Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 43 Matthieu Guillermin - Mai 2012
  • 44.
    Références entre contenus • Lors de l’import de ce champ dans B : • L’Id source va être « converti » en Id Destination en utilisant la table Map de la Migration A SELECT destid1 /* nid/tid/uid/fid */ FROM migrate_map_A /* Map table for ‘A‘ */ WHERE sourceid1 = :id_src /* id in ‘A’ src table */ • C’est l’Id « converti » qui sera enregistré dans le contenu Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 44 Matthieu Guillermin - Mai 2012
  • 45.
    Références entre contenus • Import de A SRC_A MAP_A NODE 1023 378 SRC_ID NID 1029 379 ... ... ... ... Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 45 Matthieu Guillermin - Mai 2012
  • 46.
    Références entre contenus • Import de B SRC_B MAP_B NODE_B 4204 455 SRC_ID 4605 456 NID ... ... A_ID A_REF MAP_A 1023 378 1029 379 ... ... Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 46 Matthieu Guillermin - Mai 2012
  • 47.
    En pratique... Drupal CampLyon - Optimisez vos imports de données avec Migrate 47 Matthieu Guillermin - Mai 2012
  • 48.
    Stratégies d’optimisation Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 48 Matthieu Guillermin - Mai 2012
  • 49.
    Requêtage • Comme dans tout import, le requêtage est essentiel • Limiter le nombre de requêtes • Eviter de faire une requête pour chaque ligne source • INNER JOIN / LEFT JOIN /... • Optimiser la source (si possible) • ajout d’indexes • configuration DB (innodb_buffer_pool_size,...) Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 49 Matthieu Guillermin - Mai 2012
  • 50.
    Modules « gourmands» • Désactivation de traitements lors de l’import • Pathauto : il faut mieux construire l’url « à la main » • ‘migrate_extras’ fournit un moyen de le désactiver pour une migration donnée Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 50 Matthieu Guillermin - Mai 2012
  • 51.
    Highwater Field • Pour les imports réguliers • N’importer que les données mises à jour depuis le dernier import $this->highwaterField = array( 'name' => 'last_changed', 'alias' => 'w', 'type' => 'int', ); $query->orderBy('last_changed'); Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 51 Matthieu Guillermin - Mai 2012
  • 52.
    Highwater Field • Avec le Highwater Field • Migrate ajoutera automatiquement une condition sur la requête source • Restriction des enregistrements sources à traiter • Ne fonctionne automatiquement que pour les sources : SQL, Oracle & MSSQL Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 52 Matthieu Guillermin - Mai 2012
  • 53.
    preImport() • En cas de structure de base trop « tordue » • On peut être amené à faire une première passe pour charger des éléments en mémoire • Ces éléments seront réinjectés dans chaque contenu cible • Pour cela on peut utilise la méthode preImport() Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 53 Matthieu Guillermin - Mai 2012
  • 54.
    // Called onceduring the migration process public function preImport() { parent::preImport(); $query = Database::getConnection('myDB') ->select('metas', 'm'); $query->fields('m', array( 'id_doc', 'id_meta', 'valeur')); /* ... */ $result = $query->execute(); while ($row = $result->fetchObject()) { if ($row->id_meta == self::ID_META_TITRE) { $this->metas[$row->id_doc]['titre'] = $row->valeur; } if ($row->id_meta == self::ID_META_DATE) { $this->metas[$row->id_doc]['date'] = $row->valeur; } } } Drupal Camp Lyon - Optimisez vos imports de données avec Migrate Matthieu Guillermin - Mai 2012
  • 55.
    // Called foreach source row public function prepareRow($row) { if (isset($this->metas[$row->id_doc]['titre'])) { $row->titre = $this->metas[$row->id_doc]['titre']; } if (isset($this->metas[$row->id_doc]['date'])) { $row->titre = $this->metas[$row->id_doc]['date']; } return parent::prepareRow($row); } Drupal Camp Lyon - Optimisez vos imports de données avec Migrate Matthieu Guillermin - Mai 2012
  • 56.
    En cas debesoin • Attention à la mémoire • On peut être amené à ajuster la memory_limit • Séparation en 2 migrations • Utilisation de «system of record» • Seuls les champs «mappés» seront écrasés $this->systemOfRecord = Migration::DESTINATION; Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 56 Matthieu Guillermin - Mai 2012
  • 57.
    Des questions ? DrupalCamp Lyon - Optimisez vos imports de données avec Migrate 57 Matthieu Guillermin - Mai 2012
  • 58.
    Merci pour votreattention ! @mguillermin