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
Drupal Camp 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 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
9. « 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
10. « 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
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 Camp Lyon - Optimisez vos imports de données avec Migrate 39
Matthieu Guillermin - Mai 2012
40. En pratique...
Drupal Camp Lyon - 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 Camp Lyon - 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 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
55. // 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
56. 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
57. Des questions ?
Drupal Camp Lyon - Optimisez vos imports de données avec Migrate 57
Matthieu Guillermin - Mai 2012