SlideShare une entreprise Scribd logo
1  sur  42
Télécharger pour lire hors ligne
Comment assurer la redondance de
données d’une base relationnelle vers
une base orientée document ?
THOMAS THIEBAUDET
2016-2017
1
SOMMAIRE
Sommaire ................................................................................................................................................ 1
Avant propos........................................................................................................................................... 2
Remerciements ....................................................................................................................................... 3
Introduction ............................................................................................................................................ 4
Développement....................................................................................................................................... 7
1. Analyse des solutions existantes................................................................................................. 7
2. Développement d’une application sur mesure......................................................................... 10
2.1. Analyse du besoin ............................................................................................................. 10
2.2. Environnement de développement .................................................................................. 12
3. Conception du système............................................................................................................. 13
3.1. Schématisation des données............................................................................................. 13
3.1.1. Synthétiser l’export via les annotations.................................................................... 13
3.1.2. Préparer la base documentaire................................................................................. 16
3.1.3. Vérification de la configuration................................................................................. 19
3.2. Export des données........................................................................................................... 22
3.2.1. Processus d’import / export...................................................................................... 22
3.2.2. Déclarer les associations ........................................................................................... 24
3.2.3. Gérer les associations................................................................................................ 27
3.2.4. Ajouter des filtres...................................................................................................... 31
3.2.5. Assurer l’intégrité de données sensibles................................................................... 33
3.3. Mise à jour des données ................................................................................................... 35
Conclusion............................................................................................................................................. 37
Annexes................................................................................................................................................. 38
2
AVANT-PROPOS
Développeur web passionné, je me suis formé dans un premier temps et depuis mon
plus jeune âge de manière autodidacte au développement. C’est en 2014, lorsque les chemins
de ma vie me l’ont permis, que j’ai intégré une première formation de niveau Bac + 2 à l’AFPA
de Chevigny St-Sauveur (21). J’ai également pu effectuer, durant ce temps d’apprentissage, un
stage de trois mois chez MB Salon afin d’y développer un back-office dédié à l’administration
de l’entreprise.
Fort de cette expérience, j’ai par la suite intégré le Mastère 1 - Développement Web Et
Mobile de l’école IPSSI de Paris XIIème.
Aujourd’hui, arrivé au seuil du terme de ce Mastère 1, j’ai le plaisir de mener à bien un
travail de mémoire technique, fruit de cette formation de deux ans et qui, je le souhaite, saura
refléter au mieux l’enrichissement professionnel que m’ont apporté ces deux dernières années.
De plus, je travaille actuellement pour l’entreprise Aerocontact, premier réseau
professionnel aéronautique et spatial. Aerocontact, en pleine expansion, dispose d’un portail
dédié, spécialisé dans l’actualité mais également dans l’emploi de l’industrie aéronautique,
spatiale et de la défense.
C’est dans cette entreprise que j’ai rapidement pris conscience de l’importance des bases de
données et surtout de leur utilisation. C’est pourquoi j’ai souhaité me consacrer à ce sujet dans
ce mémoire technique, qui s’intéresse aux solutions permettant d’assurer la redondance de
données d’une base relationnelle vers une base orientée document.
3
REMERCIEMENTS
J’adresse mes plus sincères remerciements à toutes celles et tous ceux qui, par leur
soutien et leur contribution, m’ont permis d’élaborer ce mémoire.
Je souhaite en premier lieu remercier l’ensemble de l’équipe de l’entreprise Aerocontact et
en particulier M. Fréderic Vergoz, mon employeur, avec qui j’ai construit une relation de
confiance et de partage et qui a su m’apporter soutien et encouragements depuis le début de ma
formation. Je remercie également mon collègue Renaud Fayolle, pour son aide précieuse et les
grandes compétences techniques qui sont les siennes et qu’il a généreusement mis à mon service
dans mon activité professionnelle.
Merci à l’école IPSSI, qui m’a donné l’opportunité d’intégrer une formation de qualité,
enrichissante tant dans les cours qu’elle dispense que grâce aux relations professionnelles
qu’elle m’a permis d’établir. Mes remerciements les plus affectueux à Muriel, secrétaire à
l’IPSSI, pour sa gentillesse et son sourire de tous les jours.
Je souhaite également adresser mes sincères remerciements à mes collègues de formation
pour leur soutien sans faille et pour l’enrichissement tant personnel que professionnel qu’ils ont
pu m’apporter, par les liens que nous entretenons comme par les croisements de compétences
qui en résultent. Mes remerciements tout particuliers à deux d’entre eux, Anthony Lemprière et
Nicolas Grévin, pour avoir offert le gîte au Bisontin que je suis lors des semaines de formation.
Merci enfin à mon compagnon, pour son aide précieuse dans l’étape de relecture de ce
mémoire.
4
INTRODUCTION
La genèse de ce mémoire repose sur un tout premier questionnement : quels sont les
avantages de la redondance d’informations d’une base à une autre ?
Premièrement, la redondance de données entre le back-office1
et le front-office permet
d’avoir deux environnements compartimentés et dédiés. Le back-office s’occupe de gérer et
d’administrer les données et le front-office2
n’a plus qu’à lire des données générées pour son
seul usage. Ce « cloisonnement de données » ou « division de données » assure une sécurité
renforcée et une meilleure répartition dans les ressources liées à l’utilisation des bases de
données.
Deuxièmement, on retrouve communément sur des bases relationnelles âgées des problèmes
d’intégrité de données dus à des modifications, à de nouvelles versions ou un travail hétérogène
exécuté par plusieurs développeurs et ce sur une longue période. Parfois, il arrive que certains
des résultats issus de ces bases soient incohérents et porteurs de bogues et donc préjudiciables
pour une entreprise.
Troisièmement, et pour finir, le fait de réaliser cet audit dans le but d’exporter des données
vers une base dédiée à lecture est la toute première étape, mais importante, ayant pour objectif
de clarifier ses bases de données actuelles. Définir des contraintes d’intégrité, des formats de
données, et même de logique, permet une meilleure appréhension des problématiques liées au
grand univers de la base de données.
De ce constat est né le questionnement qui guidera notre réflexion et nos propositions de
solutions. Ce questionnement est le suivant :
Comment assurer la redondance de données d’une base relationnelle vers une base
documentaire ?
1
Une application de back office est la partie d'un système informatique qui n'est pas accessible aux utilisateurs
finaux ou aux clients.
2
Une application de front office ou logiciel de front office est la partie d'un système informatique accessible aux
utilisateurs finaux ou aux clients.
5
Tout d’abord, il est nécessaire de définir les termes techniques et syntaxiques de cette
problématique : « redondance », « base relationnelle », « base documentaire », et la préposition
« vers », qui prend ici tout son sens.
Le terme de « redondance » renvoie au fait de répéter plusieurs fois la même chose : une
donnée « x » serait donc redondée en une donnée « y » une ou plusieurs fois. La redondance
implique donc au moins un point de départ et un à plusieurs points de destination. Dans la
langue française, le terme de redondance renvoie aux notions de l’inutile et du superflu. Je
montrerai au cours de ce mémoire que dans le domaine du développement web et de l’univers
du stockage de données, la redondance revêt un tout autre aspect.
D’autre part, nous avons d’un côté une base relationnelle et de l’autre une base
documentaire.
Par définition la base de données est « un outil permettant de stocker et de retrouver
l'intégralité des données brutes en rapport avec un thème ou une activité ». En quoi ces deux
bases sont-elles différentes ?
La base de données relationnelles est un système qui a fait ses preuves depuis les années
1970, tandis que la base orientée document est beaucoup plus récente. C’est pour cela que la
majorité des bases de données conçues avant 2010 sont stockées avec un schéma relationnel.
De nos jours, ces bases sont créées et utilisées pour du traitement de données et donc affiliées,
par définition, à un back-office par exemple, mais sont encore très utilisées.
La base de données documentaire ou orientée document a un tout autre rôle. Grâce à de
nouvelles caractéristiques, différentes de la base de données relationnelle, elle nous permet la
définition de schémas de données dynamiques et même une capacité de lecture plus
performante. C’est donc pour ces raisons, et bien d’autres non citées (Cf Annexe 1), que la base
de données documentaire est très souvent utilisée pour sa capacité de lecture améliorée, dans
ce que l’on appelle le front-office.
Dans ma problématique et entre les deux occurrences des termes « base relationnelle » et «
base documentaire », nous retrouvons le mot « vers », préposition indiquant un mouvement. De
ce fait nous avons bien un point « x », base de données relationnelle et un point « y », base de
données documentaire. C’est l’action de ce point vers l’autre qui définit la notion même de
redondance. Nous souhaitons exporter les données de « x » à « y ».
6
Afin de répondre et de trouver des solutions au questionnement qui nous occupe, nous
analyserons dans un premier temps quelles sont les solutions déjà existantes ; pour, dans une
seconde et dernière partie, nous intéresser à la schématisation et à l’export des données dans le
cadre du développement de cette application sur mesure.
7
DEVELOPPEMENT
1. Analyse des solutions existantes
Plusieurs outils existent actuellement et sont disponibles afin de répondre, plus ou moins
bien, à notre problématique : assurer la redondance de données d’une base SQL3
à une base
NoSQL4
. Durant ma phase de recherches, j’ai pu relever trois solutions sérieuses. J’ai tenté de
les examiner en détail afin de vérifier qu’elles soient réellement adaptées à nos besoins. Voyons
ensemble, et une à une, si ces solutions sont à envisager.
• Solution numéro 1 : Utiliser le format CSV5
Le premier choix que nous avons est d’exporter notre base de données MySQL, table par
table, au format CSV, avant de l’importer dans notre base MongoDB. En effet, l’aspect
simplissime du document texte .csv le rend interprétable par notre SGBD document.
Malheureusement, même si ce procédé nous assure une mise en place rapide, nous devons
pallier à plusieurs problèmes. En effet, cette solution ne gère pas les relations et ne vérifie pas
l’intégrité des données à exporter. Compte tenu de ces difficultés, nous n’irons pas plus loin
dans l’examen de cette solution.
LES PLUS LES MOINS
Compatible MySQL / MongoDB Ne gère pas les relations
Mise en place rapide Ne vérifie pas l’intégrité avant export
3
Le SQL (Structured Query Language) est un langage permettant de communiquer avec une base de données.
4
NoSQL désigne une famille de systèmes de gestion de bases de données (SGBD) qui s'écarte du paradigme
classique des bases relationnelles.
5
« Comma-separated values », connu sous le sigle CSV, est un format informatique ouvert représentant des
données tabulaires sous forme de valeurs séparées par des virgules.
8
• Solution numéro 2 : Créer un script sur mesure
Le deuxième choix qui s’offre à nous est de scripter un ensemble de procédures afin
d’exporter l’ensemble de nos données. C’est-à-dire réaliser un code PHP qui exportera, table
par table, colonne par colonne, élément par élément, les données qui nous intéressent. Cette
solution a le mérite d’être sur mesure et est donc adaptée à notre projet. Malheureusement, c’est
une méthode fastidieuse qui ne sera pas déployable rapidement. Le code ne pourra pas être
réutilisé et nous devrons redévelopper de nouveaux scripts pour assurer la mise à jour des
données dans le temps.
LES PLUS LES MOINS
Sur mesure et donc adapté à notre projet Fastidieux à mettre en place
Possibilité de traitement sur les données N’assure pas la mise à jour des données
Code non réutilisable
• Solution numéro 3 : Mongify (1.3.2)
Cette dernière solution est une application, développée en RUBY6
, qui a pour vocation
d’assurer l’import de nos données relationnelles vers MongoDB. Mongify est utilisable
uniquement en ligne de commande et permet de créer des schémas de données à exporter. De
plus, nous devons fournir des fichiers de configurations en RUBY. Mongify gère les relations
du premier degré dans l’import des données et assure l’intégration de documents.
Malheureusement, quelques points négatifs sont à noter : la vérification de l’intégrité des
données est faible avec Mongify. En effet, seule la vérification concernant le type de données
est disponible, et c’est un point définitivement bloquant pour notre projet actuel. De plus, son
système de fonctionnement n’assure pas la mise à jour des données, mais seulement l’export et
l’import. En utilisant Mongify, et dans l’objectif de mettre à jour mes données, je serai forcé de
supprimer les données actuelles de MongoDB avant de renouveler l’import. Cette méthode
6
Ruby est un langage de programmation libre, interprété et orienté objet.
9
n’est donc pas optimisée pour assurer la redondance de données de manière continue. On notera
également que l’injection de documents n’est pas non plus disponible dans sa version actuelle.
LES PLUS LES MOINS
Gère les relations du premier degré N’assure pas la mise à jour des données
Utilisation simplifiée en ligne de commande Beaucoup de configuration à renseigner
Vérification faible de l’intégrité des données
Après cette inspection des outils disponibles, j’ai choisi de totalement ignorer l’utilisation des
documents CSV pour assurer la redondance de données que je recherche. Pour ce qui est des
solutions numéro deux et numéro trois, elles ne correspondent que partiellement à mon projet.
Toutefois elles m’ont aidé dans le choix d’une solution sûre.
J’ai donc choisi de « fusionner », en quelques sortes, ces deux dernières solutions de manière
à réutiliser l’ensemble de leurs avantages et de pallier à leurs inconvénients.
A travers ce mémoire, nous verrons les étapes nécessaires afin de concevoir, puis développer,
une application sur mesure nous permettant d’assurer la redondance de données d’une base
relationnelle vers une base orientée document.
Commençons, dès maintenant, l’analyse précise de nos besoins à travers ce deuxième
chapitre.
10
2. Développement d’une application sur mesure
2.1. Analyse du besoin
A travers cette analyse du besoin, nous allons répertorier ici, l’ensemble des
fonctionnalités nécessaires à notre application. Chaque point référencé possèdera au moins un
chapitre lui étant entièrement dédié.
Tout d’abord, nous souhaitons que notre application soit simple d’utilisation. Ce soft
n’ayant pas besoin d’un navigateur, nous aurons besoin d’utiliser notre terminal. Nous
aborderons ce point dans le chapitre « Synthétiser l’export via les annotations » où nous
trouverons, dans ces « annotations », une aide quasi-indispensable.
Ensuite, nous souhaitons avoir le moins possible de configurations. Plus que ça, nous
souhaitons également pouvoir nous assurer que la configuration donnée soit bien valide. Ces
deux besoins seront détaillés dans les chapitres « Préparer la base documentaire » et
« Vérification de la configuration ».
Nous aurons vraisemblablement besoin d’exporter des données de MySQL et de les
importer dans MongoDB. Pour assurer cette fonctionnalité essentielle, nous approfondirons le
sujet, point par point, dans un chapitre propre à la redondance de données : « Processus
d’import / export ».
Indispensable à nos besoins, nous souhaitons, de manière optimisée, nous occuper de la
gestion des relations. Nous désirons également que cette capacité à assurer les associations soit
facilement paramétrable. Ces deux parties seront analysées dans « Déclarer les associations »
et « Gérer les associations ».
Les données que nous devrons traiter ne sont pas homogènes dans leurs formats car elles
ont été altérées durant plus d’une décennie. La transformation de ces données, grâce aux filtres,
solutionnera cette préoccupation dans le chapitre « Ajouter des filtres ».
L’altération continue de ces données peut provoquer plus que des problèmes de format.
Certaines données, telles que les clés primaires et clés étrangères, non valides, sont considérées
comme non-intègres et donc problématiques pour notre application. Ces données, non intègres,
sont problématiques pour l’état de santé général de notre soft. En effet, elles sont porteuses de
11
bogues potentiellement nuisibles. Nous examinerons ce désagrément dans « Assurer l’intégrité
de données sensibles ».
Pour finir, dans le chapitre « Mise à jour des données », nous passerons en revue les étapes
nécessaires à la mise à jour des données de manière à assurer une redondance continue des
données.
Ces besoins étant établis, attelons-nous maintenant au développement de cette application
sur mesure. En trois parties nous aborderons, premièrement, la schématisation des données ou
méta-données. Nous verrons ensuite le fonctionnement du processus d’import/export à travers
différentes sous-catégories. Enfin nous parcourrons les étapes de mise à jour.
12
2.2. Environnement de développement
Par habitude, j’ai utilisé PHPSTORM comme IDE7
; mais par besoin, j’ai développé
cette application sous linux. En effet, Docker8
a été le moteur central de mon environnement de
développement et n’est pleinement fonctionnel que sous linux.
J’ai conçu cet environnement de développement en trois conteneurs distincts : PHP-CLI,
MySQL et MongoDB. Le premier conteneur exploitera PHP en lignes de commande, et
MySQL et MongoDB émulerons des serveurs de base de données. Vous pourrez retrouver la
configuration du docker-compose.yaml dans les annexes de ce mémoire.
Par ailleurs, voici une liste non-exhaustive des librairies importées à notre application :
- doctrine/orm
- cocur/slugify
- gedmo/doctrine-extensions
- symfony/validator
- jdorn/sql-formatter
Nous étudierons de plus près MongoDB et installerons sa version 3.2 : des nouvelles
fonctionnalités ont fait leur apparition. L’une d’entre elles, considérable, est la validation des
documents avant persistance des données.
Concernant MySQL, nous utiliserons sa dernière version stable, qui date de 2013 : la 5.6.
C’est celle qui est actuellement utilisée sur nos serveurs d’entreprise et qui nous assure une
compatibilité avec cette nouvelle application.
Pour visualiser le contenu des bases de données, durant notre phase de test, nous installerons
deux SGBD9
: « MongoDB Compass » pour visualiser nos données stockées sous MongoDB
et « phpMyAdmin » sous MySQL.
7
« integrated development environment » Un environnement de développement est un ensemble d'outils pour
augmenter la productivité des programmeurs qui développent des logiciels.
8
Docker est un logiciel libre qui automatise le déploiement d'applications dans des conteneurs logiciels.
9
« Système de gestion de base de données »
13
3. Conception du système
3.1. Schématisation des données
3.1.1. Synthétiser l’export via les annotations
Avant toute chose, il est important de rappeler que l’annotation est un élément qui
permet l’ajout de méta-données à une classe, un attribut, des fonctions etc. Depuis la croissance
de popularité des frameworks PHP tels que Symfony ou Laravel, pour n’en citer que deux, on
trouve des annotations dans la plupart des fichiers PHP.
Ces annotations sont utilisées pour documenter le code de façon générale. On retrouve des
indications sur la dépréciation d’éléments et de fonctions et parfois une aide dans l’utilisation
des méthodes présentes. Leur utilisation est très appréciée des développeurs tant dans l’emploi
du code que dans la conception de système divers.
Dans le cadre du développement de la solution de redondance de données, les annotations
m’ont permis un gain de temps non négligeable dans l’élaboration de mon application qui
s’explique pour deux raisons : la malléabilité et la réutilisation d’annotations existantes. En
effet, la souplesse dans la création de méta-données est considérable. J’ai pu élaborer une
syntaxe simple et adaptée à mes besoins dans une utilisation quotidienne de l’application.
Utiliser des annotations existantes a simplifié ma phase de développement. Sur la base du
framework Symfony, j’ai pu réutiliser, sans encombre, certains des éléments de la classe
SymfonyComponentValidatorConstraints, généralement appelée « Assert 10
», dans
la gestion des contraintes d’export.
La librairie de Doctrine11
est également riche en ressources indispensables pour mes besoins
en récupération d’informations relatives aux bases de données : index, appellation, type,
relation…
S’il est simple d’ajouter des méta-données, par exemple à un modèle, il est également aisé
d’en récupérer les informations. On appelle cela, dans notre cas, une analyse de classe.
10
« Faire valoir ».
11
« Doctrine » est une couche d’abstraction à la base de données.
14
Depuis les débuts de PHP, dans ses premières versions, il était beaucoup plus
compliqué d’analyser son code en lui-même. D’ailleurs l’ajout de la PHP DOC12
n’a eu lieu
que vers les années 2000.
Mais c’est avec PHP en version 5, et plus précisément la version 5.1 de 2005, qu’apparut
une classe actuellement très populaire : ReflectionClass.
C’est grâce à elle, en grande partie, qu’ont vu le jour les premières applications à
implémenter un « moteur », destinées à tirer le meilleur parti d’une classe : l’analyse des méta-
données pour en extraire des informations ; c’est pourquoi je l’ai utilisée dans le développement
de mon application.
D’un point de vue technique, dans la récupération de ces méta-données, j’ai pu répartir le
processus d’analyse en trois classes : ModelClassParser, ModelAttributesParser et
ModelFunctionsParser.
ModelClassParser se charge d’analyser les annotations spécifiques à une classe, situées
au-dessus de la déclaration de cette dernière. On trouvera des informations concernant l’export
de la table sous MySQL annotées au document.
/**
* @EXPORTdocument(table="users_3", document="users")
*/
class User
{}
ModelAttributesParser s’occupera de la récupération des méta-données associées aux
attributs de notre entité. C’est ici que nous pourrons filtrer à l’export nos données en modifiant
leur contenu ou en assurant leur intégrité et les contraintes avant l’import dans leur document
de destination.
/**
* @EXPORTfilter("upper")
* @EXPORTintegrity(unique=true, format="dw")
*/
protected $reference;
12
Standard formalisé pour commenter le code PHP.
15
ModelFunctionsParser a été créé, mais n’est pas encore implémenté dans mon
application. En effet, je n’ai pas trouvé d’utilité à annoter des méthodes dans mon cas ; bien
que dans une version d’amélioration et d’optimisation de ce soft, il serait intéressant d’utiliser
des filtres personnalisés d’export avec un système d’annotation de fonctions.
Ce processus d’analyse va pouvoir alors générer un fichier de configuration spécifique pour
chaque modèle annoté. L’ensemble de ces fichiers sera importé au manifeste : notre fichier de
configuration générale.
16
3.1.2. Préparer la base documentaire
L’étape de synthétisation de notre classe étant terminée, nous allons pouvoir définir
les informations essentielles à l’export de notre base de données relationnelle vers notre
nouvelle base documentaire.
Quels sont les éléments indispensables pour assurer notre redondance de données ?
Tout d’abord, il nous faut connaître l’actuelle configuration de la base de données à extraire.
Mais il est également nécessaire de définir un nouveau schéma sur notre base de données
documentaire. Dans le but d’importer de nouvelles données filtrées, triées, intègres, il est
indispensable d’associer également à ce manifeste l’ensemble des modèles annotés.
Ce fichier « manifesto » est structuré en YAML13
, tout d’abord car sa structure fait que son
contenu est facilement lisible pour un humain, mais aussi parce que plusieurs librairies PHP
sont proposées pour gérer ce format.
• Configuration d’une base MySQL
On a besoin, premièrement, du nom de la base à exporter et des informations de connexion
ainsi que d’éléments pour assurer la mise à jour des données après un export réussi.
Pour la connexion, nous trouvons le nom d’hôte, le nom d’utilisateur, le mot de passe, le
port et le « charset14
» pour en définir l’encodage des données.
Pour assurer la mise à jour des lignes en documents, nous aurons besoin d’un point de
référence sur chaque table dans notre base hôte. Une fois ces options indexées dans notre fichier
de configuration, nous devrons rajouter une nouvelle colonne dans nos tables représentées par
nos modèles annotés. Nous reprendrons le même nom que notre manifesto.yaml et
définirons cette colonne comme étant de type « VARCHAR », avec une taille maximale de 24
caractères (correspondant à la taille l’ObjectId15
de notre document MongoDB).
L’essentiel des données primaires étant enfin défini pour assurer l’export, nous pouvons
maintenant recenser les éléments garantissant l’import vers notre base documentaire.
13
Acronyme de « Yet Another Markup Language » YAML est un format de représentation de données par
sérialisation Unicode.
14
Jeux de caractères codés.
15
Classe qu’utilise MongoDB pour générer des identifiants de 12-byte
17
• Configuration d’une base MongoDB
Pour connecter notre base documentaire, nous aurons besoin des mêmes informations de
connexion : le nom d’hôte, le nom d’utilisateur, le mot de passe et le port. Par défaut, le nom
de la base de données sera identique à celle de MySQL. Toutefois, une option permettra d’en
assurer la personnalisation.
Certaines options doivent être intégrées dans la création de nouvelles collections. Si elles
ne sont pas renseignées, elles conserveront leur valeur par défaut. Il s’agit du nombre maximum
de documents pouvant être contenus par une collection et de sa taille maximale.
Il était très important d’assurer l’intégrité des données durant l’export car, je le rappelle,
cette solution est adaptée aux bases de données destructurées souhaitant disposer d’une base de
données documentaire claire, saine et intègre. Par conséquent, j’ai intégré deux options de
configurations associées aux collections ayant pour but de valider un document lors de sa
persistance et de sa mise à jour : validationLevel et validationAction.
- validationLevel permet de gérer le degré de validation à appliquer avant
d’enregistrer un document. Il peut être désactivé (off), modérément appliqué (moderate)
ou très exigeant (strict).
- validationAction rajoute une couche de sécurité en permettant de générer, en
fonction des conditions de validation, un code d’erreur qui stoppe l’insertion ou bien un
code d’avertissement permettant de log durant l’import des données vers MongoDB.
En réalité, ces options de configuration sont directement reliées aux annotations de modèles
assurant l’intégrité des données, et seront expliquées plus en aval (cf partie 3.2.4).
Pour schématiser cette préparation « d’export/import » de données ou de redondance de
données, voici un aperçu du fichier de configuration défini en fonction de nos besoins.
# manifesto.conf
connection:
- mysql:
db_name: "monsite"
hostname: "hostname.mysql.com"
port: 3306
user: "userMysql"
password: "p@ssMysql"
charset: ""
- mongo:
18
db_name: ~
hostname: "hostname.mongo.com"
port: 27018
user: "userMongo"
password: "p@ssMongo"
export:
update_on: "mongo_id"
import:
init:
max_doc_size: ~
max_doc_count: ~
validation:
level: "strict"
action: "warning"
imports: ['user']
19
3.1.3. Vérification de la configuration
Pour assurer le bon fonctionnement de notre configuration, trois points essentiels sont
à vérifier :
- La connexion MongoDB est-elle fonctionnelle ?
- La connexion MySQL est-elle fonctionnelle ?
- Les modèles importés sont-ils valides ?
- Le fichier de configuration est-il valide ?
Tout d’abord, vérifier le fichier de configuration semble être la première étape à réaliser. En
effet, toutes les autres vérifications dépendent de ce manifeste. On contrôle en premier lieu si
le fichier peut être « parser 16
» ; puis, si l’ensemble des informations récupérées par la classe
ManifestoParser est intègre avec ce que nous attendons.
Cette classe d’analyse du fichier de configuration est similaire aux classes créées
précédemment pour parser les annotations des modèles, à la simple différence que celle-ci
utilise des librairies spécifiques à l’analyse du format YAML. Le but de cette dernière est de
recenser chaque information sur l’import et l’export afin de construire un objet appelé
ExportConfigurator qui contiendra l’intégralité des données de configuration.
La classe ValidatorConfigurator, elle, interrogera l’objet ExportConfigurator
pour vérifier le format et le contenu des données collectées durant le processus d’analyse du
manifeste.
16
« Analyser »
20
Schéma du processus de validations du fichier de configuration
La même technique de validation a été déployée pour vérifier les modèles et ses méta-
données. Les classes ModelAttributesParser et ModelClassParser génèrent, par un
procédé identique, un objet AnnotatorConfigurator ayant pour but d’être consulté par une
nouvelle classe : ValidatorAnnotator. Cette dernière s’occupera de vérifier que les
annotations recueillies sont bien valides et compréhensibles par notre application. La validation
doit bien sûr s’exécuter pour autant de modèles qu’il y a d’importés.
21
Schéma du processus de validations des modèles annotés
Pour répondre à la problématique de vérification avec MySQL et MongoDB, il suffit
d’utiliser la méthode getConnection du manager de doctrine et en y associant bien sûr les
identifiants des deux connexions avec le fichier manifesto.yaml. Un script simple nous
permet de faire un appel aux deux bases et de retourner un état pour chacune d’elle.
Comment rendre ces étapes de vérifications simples et rapides ?
En tant que futur utilisateur de ce soft, je souhaite pouvoir vérifier de façon automatique si
la configuration est fonctionnelle, sans avoir à vérifier manuellement tous mes fichiers. La
solution la plus pratique que j’ai trouvée est de scripter, étape par étape, les actions nécessaires
avant toute utilisation future de l’application. A la mode du PHP en ligne de commande et parce
que l’ensemble de mon programme tourne sous PHP, j’ai décidé de créer un fichier effectuant
les vérifications nécessaires en différentes procédures, avant de retourner au terminal un code
d’erreur ou un message de succès.
Pour vérifier l’intégrité de la configuration avant l’export, la commande suivante est
maintenant disponible pour nous décharger dans l’inspection du code et des différents fichiers
: php verification.php
22
3.2. Export des données
3.2.1. Processus d’import / export
Pour bien comprendre le fonctionnement de l’application et l’import/export de
données, il est important d’avoir au préalable une vision d’ensemble. Voici un schéma simple
qui nous permettra d’y voir plus clair.
Schématisation du système d’import / export
Deux classes, ConnectImport et ConnectExport, interrogent les deux configurateurs
dans l’objectif d’assurer une connexion pour l’import avec MySQL et pour l’export avec
MongoDB.
La classe DataImport s’occupe de générer une requête personnalisée afin de récupérer les
données associées à notre modèle. Cette dernière communique avec le système de traitement et
de gestion des relations, de manière à collecter les filtres annotés à la classe. Cette
personnalisation nous permettra d’ajouter des conditions supplémentaires avant de récupérer
des lignes de données. Par exemple, on pourra filtrer les produits et n’exporter que ceux qui se
trouvent en stock. Les notions qui concernent les filtres de classe et d’attributs seront abordées
dans un chapitre dédié à ce seul sujet (cf. partie 3.2.4 - Ajouter des filtres).
23
Le système de traitement des données est un ensemble de classes qui sont dédiées à
accomplir une tâche spécifique. On retrouvera des classes assurant l’intégrité des données, les
filtres vus précédemment et la gestion des différents types de relations.
La classe DataExport s’occupera, comme son nom l’indique, de l’export des données de
notre base relationnelle à notre base orientée document. Cette dernière prendra en paramètre
notre requête d’insertion formatée en JSON17
. A cette étape de notre processus d’export, les
données ont été filtrées et les relations ont été gérées. Mais les données ne seront considérées
comme intègres qu’après leur propre persistance sous forme de documents. En effet, MongoDB
dispose d’un système de validation natif depuis sa version 3.2 et nous permettra, par des règles
de validations, également formatées en JSON, de persister, ou non, nos données.
Processus de persistance des données
17
JSON est un format de données textuelles.
24
3.2.2. Déclarer les associations
Bien que MongoDB soit une base orientée document, son mode de fonctionnement
permet nativement la gestion d’associations. Les « relations » de MySQL sont appelées
« Embedded Documents18
» dans l’univers de MongoDB. L’utilisation des associations est
donc possible mais doit se faire avec parcimonie car notre base documentaire n’a pas été conçue
pour être performante dans la gestion relationnelle.
Alors comment intégrer de façon adéquate certaines relations à notre document durant sa
phase d’export ?
Demandons-nous si les données contenues dans la relation sont utiles pour notre front-office.
Si cette première interrogation penche vers positif, alors nous devrons effectivement insérer ces
nouvelles données à notre document, mais pas de n’importe quelle façon.
• Intégrer l’ensemble des données jointes dans notre document
Prenons un exemple simple : j’ai un modèle Product avec une référence. Ce produit
possède une relation « one to many19
» avec Category, ce qui signifie que pour un produit
nous aurons zéro à une catégorie ; et, à l’inverse, que pour une même catégorie, nous aurons un
à plusieurs produits associés. Dans ce cas, il n’est pas nécessaire de créer un nouveau modèle
pour Category mais d’en injecter les données.
Pour gérer l’import des catégories dans notre modèle Product, nous devons ajouter de
nouvelles annotations, de façon à déclarer qu’il s’agit d’un document à injecter, mais aussi de
définir quels éléments sont à importer.
/**
* @EXPORTinject(document="Categories", related="id_cat" {"name",
"description"})
* @EXPORTcolumn("categories_id")
*/
protected $categories;
18
« Documents intégrés »
19 « Un à plusieurs »
25
La relation est configurée grâce aux méta-données « related 20
» des annotations
EXPORTinject et EXPORTcolumn. La première annotation fait référence à l’identifiant
unique de notre catégorie, de manière à pouvoir assurer la liaison entre un produit et une
catégorie. La deuxième annotation, elle, fait référence au nom de la colonne vers laquelle pointe
l’attribut « categories ».
Maintenant que nous avons déclaré l’injection des données « name » et « description » à
notre produit, nous terminerons par annoter notre modèle Category, de manière à connaître
sa table de référence dans notre base relationnelle.
/**
* @EXPORTdocument(table="categories")
*/
class Category
{
}
• Créer un nouveau document et le référencer dans notre document actuel
Pour rappel, cette technique de « Embedded Documents » n’est pas à utiliser à la légère.
Les performances de lecture sur notre front-office ne seront pas optimales. En effet, plutôt que
de charger un seul document, MongoDB devra en charger deux en effectuant du traitement
supplémentaire pour récupérer ce deuxième document. Toutefois, certaines contraintes, liées à
l’entreprise par exemple, ne nous permettent pas d’intégrer de façon brute les éléments dans
notre unique modèle et cette technique reste la seule solution pour référencer un modèle externe.
Déclarer ce type d’association reste aussi simple que dans le cas précédant. Nous utiliserons
l’annotation EXPORTeject pour déclarer notre modèle à intégrer, mais nous n’aurons plus
besoin de définir les attributs de Category.
/**
* @EXPORTeject(document="Categories", related="id_cat")
* @EXPORTcolumn("categories_id")
*/
protected $categories;
20
« Lié à »
26
Occupons-nous pour finir de configurer notre classe Category. Comme plus tôt, nous
devons annoter à cette dernière des informations de correspondance à sa table MySQL. Nous
en profiterons également pour exporter les attributs « name » et « description », sans vérifier
leur intégrité et sans leur ajouter de filtres.
/**
* @EXPORTdocument(table="categories")
*/
class Category
{
/**
* @EXPORT
*/
protected $name;
/**
* @EXPORT
*/
protected $description;
}
L’essentiel des informations permettant de déclarer les relations a bien été communiqué. Il
nous faudrait maintenant nous intéresser à la manière dont sont gérés ces deux types de
relations.
27
3.2.3. Gérer les associations
Nous venons de synthétiser nos associations selon deux schémas type : les
documents intégrés et les documents injectés.
La partie « annotation » étant terminée, voyons maintenant, et en deux parties, comment
sont gérées ces relations.
• Injection de documents
Rappelez-vous, injecter un document signifie l’intégrer de façon brute dans notre document
actuel. C’est la méthode la plus performante et celle à utiliser en priorité afin d’exploiter au
maximum le potentiel de MongoDB.
Dans notre système de traitement de données, nous retrouvons toutes les classes utilisées
pour développer cette gestion des relations. Une classe un peu plus spécifique,
InjectDocumentData, se démarque des autres. Elle est le maillon solide du gestionnaire de
relation dans l’injection des données d’un document.
D’un point de vue technique, cette classe rentre en action dès la fin des opérations de
DataImport. En reprenant notre exemple avec le modèle Product, et à ce stade, nous aurions
accès à une liste de produits à exporter. Si, et seulement si, le modèle dispose de contraintes
relationnelles, la classe InjectDocumentData sera instanciée21
. Grâce aux méta-données
fournies dans notre modèle : (nom du document externe, clé(s) primaire(s) et secondaire(s),
données à extraire) nous pouvons facilement de là, générer une nouvelle requête avec ces
informations et l’aide de notre classe ConnectImport. Les données récupérées sont ajoutées
dans un tableau ayant comme index le nom de l’attribut annoté et sont traduites en JSON. Ces
nouvelles données brutes sont ensuite injectées au document actuel pour en assurer la lecture.
A l’heure actuelle, cette application, ne prend pas en compte les options de filtres et
d’intégrités dans la gestion des injections de documents.
21
« Initialiser à partir d’un espace mémoire réservé »
28
• Intégration de documents
Techniquement, je dirais que cette gestion d’association automatisée a été la plus
complexe à traiter et même à appréhender. J’ai toutefois réussi à exploiter une solution que je
vais vous exposer. Conjointement à cette démonstration, seront bien sûr présentées les
imperfections que j’ai pu relever durant la phase de développement.
La classe EmbeddedDocumentData fait également partie de l’ensemble du système de
traitement, au côté de InjectDocumentData. Plutôt que de requêter de nouvelles données à
injecter, cette classe, une fois instanciée, va stopper le processus actuel pour exécuter
pleinement l’ensemble des tâches qui lui ont été assignées et qui la caractérisent : créer un
deuxième document et ajouter un pointeur sur le document actuel.
Plutôt que d’injecter des données et de persister notre document, nous devrons passer par
plusieurs étapes obligatoires :
- Créer un nouveau document
- Ajouter ses filtres
- Assurer son intégrité
- Sauvegarder le pointeur vers ce nouveau document
- Reprendre le processus initialement stoppé par EmbeddedDocumentData
- Persister le document source
Toutes ces étapes se ressemblent et sont répétitives entre le document source et le document
à intégrer. De plus, l’échec d’une des étapes est préjudiciable pour le reste des opérations à
venir. Voici la première critique négative qui s’est dégagée de mon analyse dans cette gestion
des relations. Malheureusement je n’ai pas pu, à l’heure actuelle, optimiser cette partie de
développement.
29
Comme vous l’avez remarqué, intégrer un nouveau document revient à reproduire le
comportement de la classe DataImport et de son système de traitement, et ce, à l’intérieur de
l’instance courante. Notre code est donc réutilisé à travers l’intégration de ce nouveau
document. Je relève tout de même cette fois une critique positive dans ce développement : leq
processus de création d’un document source et d’un document intégré étant identiques, il nous
assure une meilleure évolutivité de l’application et des contraintes similaires dans les étapes de
construction de notre document.
Pour finir ce dernier point sur les relations, j’aimerais signaler que je me suis limité dans la
gestion des intégrations de documents intégrés dans un document intégré, depuis un document
source. C’est-à-dire que nous avons un « produit » qui possède une relation avec un
« fabricant ». Ce même fabricant possède une relation avec une « maison-mère ». « Maison-
mère » est une relation du deuxième degré pour notre produit.
Dans le cas où nous souhaiterions intégrer le document « maison-mère » dans le document
« fabriquant », et ce document « fabriquant » dans notre document source « produit », nous
serions bloqués par l’application. La raison pour laquelle je n’accepte qu’un degré de relation
dans la gestion de documents intégrés est simple et a déjà été explicitée : MongoDB est orienté
document et n’est pas adapté à la gestion des relations, ou « Embedded Documents ». (Cf.
Annexes)
Schématisation d’une relation du troisième degré non valide
Cependant, rien ne nous en empêchera d’injecter le document « maison-mère », dans le
document « fabriquant », et d’intégrer ce dernier document dans le document source
« produit ». En effet, l’injection de document ne stoppe pas le processus actuel, à l’inverse des
30
intégrations. Pour rappel, l’injection de document, représentée par InjectDocumentData, ne
fait que requêter et insère des données brutes. Pour schématiser cette représentation, nous
utiliserons pour cela les annotations dans trois documents séparés. (Cf. Annexes)
Schématisation d’une relation de deuxième degré valide
31
3.2.4. Ajouter des filtres
Durant la phase de traitement des données, l’ajout de filtres constitue une étape
importante dans l’export de celle-ci. Plusieurs types de filtres ont vu le jour : on retrouve d’un
côté les filtres de classe et de l’autre des filtres d’attributs. Ces filtres sont définis intégralement
grâce aux annotations EXPORTfilter sur des attributs et EXPORToption sur des classes.
Les fonctionnements de ces filtres étant différents, nous allons les analyser séparément.
• Filtres de classe
Les filtres de classe permettent de personnaliser les éléments récupérés sous MySQL, afin
d’exporter non pas l’ensemble d’une table mais des résultats filtrés au besoin du front-office.
Pour donner un exemple d’utilisation du filtre de classe, je reprendrai mon modèle « Produit »
et ajouterai un filtre d’export ciblant les produits actuellement en vente, traduit par un stock
d’au moins supérieur à « 1 ».
/**
* @EXPORTdocument(table="products")
* @EXPORToption("stock",">=",1)
*/
class Product
{
}
L’annotation EXPORToption prendra en paramètre des éléments identiques à ce que
prendrait n’importe quel type d’ORM22
ou d’ODM23
: la base de recherche, dans notre cas
« stock », puis la condition, ici « supérieure ou égale » et enfin notre variable de comparaison :
« 1 ». De ce fait nous n’exporterons que les produits ciblés pour la vente.
Côté développement, cette option interagit avec le « Query Builder24
» de Doctrine afin
d’ajouter des nouvelles conditions dans notre récupération de produits en stock.
22
« object-relational mapping »
23
« object-document mapping »
24
« Générateur de requête »
32
• Filtres d’attributs
Les filtres d’attributs sont utilisés pour formater des données avant de les exporter sous
MongoDB. Nous retrouvons ces derniers employés sur des chaines de caractères, des tableaux,
des objets… Ces filtres d’attributs sont similaires aux filtres disponibles par certains moteurs
de template PHP. La différence notable, comparé à Twig25
ou Smarty26
, provient du fait que
ces filtres sont appliqués avant l’enregistrement des données et non pendant leur lecture. Plus
encore que de gagner en temps de traitement, ces filtres pré-enregistrement évitent aux
intégrateurs des contraintes dans l’affichage de données. Formater les données en amont permet
donc de faciliter la lecture en se déchargeant de certaines obligations d’affichage.
Les filtres d’attributs utilisés dans notre application restent primaires, mais nous éviterons
donc plusieurs manipulations de données lors de leur affichage. On retrouvera des filtres
spécifiques aux chaines de caractères : convertir les caractères en minuscule ou majuscule,
supprimer les espaces en début et fin de chaînes, retirer d’éventuelles balises HTML27
…
Certains filtres sont applicables uniquement aux tableaux : trier un tableau par ordre ascendant
ou descendant, ne récupérer qu’une partie d’un tableau… Bien sûr, ces filtres ne seront
fonctionnels que sur des tableaux sérialisés28
en base de données.
Voici un exemple de filtres annotés au modèle Product où nous souhaitons obtenir le nom
du produit en majuscule et la référence nettoyée d’éventuels espaces en début et fin de chaîne.
class Product
{
/**
* @EXPORTfilter("uppercase")
*/
protected $name;
/**
* @EXPORTfilter("trim")
*/
protected $reference;
}
25
Moteur de template utilisé par défaut sous Symfony
26
Moteur de template utilisé par défaut sous PrestaShop
27
« L’HyperText Markup Language, généralement abrégé HTML, est le format de données conçu pour
représenter les pages web ».
28
La sérialisation est un processus visant à coder l'état d'une information qui est en mémoire sous la forme d'une
suite d'informations plus petites.
33
3.2.5. Assurer l’intégrité de données sensibles
Vérifier l’intégrité des données est une étape relativement similaire à la gestion des
filtres d’attributs. Pour les filtres, nous récupérons une donnée puis la formatons selon nos
besoins avant de persister notre entité. Nous n’attendons rien en retour des transformations. A
l’inverse, les vérifications d’intégrité ont pour but de nous indiquer si les données sont bien
valides avant de les persister.
Grâce à MongoDB, depuis sa version 3.2, nous disposons d’un validateur intégré et
performant. Très facile d’utilisation, il nous permet d’établir des règles de validation à la
création d’une collection. Ces contraintes sont traduites des annotations EXPORTintegrity
en JSON, à destination des options de création de la collection.
Schématisation des étapes de validation sous MongoDB
Trois éléments assurant l’intégrité des données ont été mis en place pour notre application :
le format, l’unicité et le type. Bien sûr, il est important de rappeler que d’autres éléments
pourront venir se greffer à notre soft dans ses prochaines versions.
• Vérification d’unicité
Cette option nous permet de vérifier qu’un attribut est bien unique dans notre base de
données relationnelle avant l’export. Pour assurer cette inspection, notre classe
EnsureAttributesUnicity, du système de traitement des données, requête la table
correspondante et s’assure que la donnée est bien unique. Les méta-données à ajouter sont :
/**
* @EXPORTintegrity(unique=true)
*/
protected $email;
34
• Vérification de format
Grâce au paramètre « format » de notre annotation, nous pouvons nous assurer que la donnée
est bien valide à nos yeux et peut donc être persistée sans problème. La valeur du format est
renseignée avec l’aide des expressions régulières29
. Pour traiter ces informations et assurer
l’intégrité du format, j’utilise une fonction native PHP 4 : preg_match.
/**
* @EXPORTintegrity(format="/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-
9]|3[0-1])-[0-9]+$/")
*/
protected $reference;
• Vérification de type
Pour finir ce chapitre sur l’intégrité des données, voici la dernière option mise en place sur
notre application : la vérification du type. Bien sûr, quand on parle de type, il s’agit bien du
type d’un attribut. Un test est effectué afin de vérifier si le type de donnée récupérée est valide
pour le validateur MongoDB. Côté PHP, nous avons également une fonction native PHP 4 :
gettype pour s’assurer de la bonne récupération de cette information. En annotation on
indiquera :
/**
* @EXPORTintegrity(type="double/")
*/
protected $price;
29
« Expression régulière ou REGEX est une chaîne de caractères, qui décrit, selon une syntaxe précise, un
ensemble de chaînes de caractères possibles. »
35
3.3. Mise à jour des données
La mise à jour des données s’effectue simplement grâce à l’ajout du champ
« mongo_id » dans les tables à exporter. Pour rappel, notre configuration prend en charge les
mises à jour, mais s’assure aussi de la présence de cette nouvelle colonne grâce au fichier
manifesto.yaml.
export:
update_on: "mongo_id"
L’initialisation de « mongo_id » intervient lors de la persistance d’un document. Si, et
seulement si, le document est jugé valide par MongoDB et est persisté en base de données, un
nouveau processus de mises à jour est lancé. La classe EnsureUpdateData est alors instanciée
et est pleinement connectée avec ConnectImport afin d’assurer l’ajout de l’identifiant unique
du document dans notre champ « mongo_id ». Cette étape est la dernière à être réalisée dans
l’export des données.
Schématisation de l’intervention du processus de mises à jour
Afin de nous assurer une redondance continue et fonctionnelle, nous détaillerons les
différents process de mises à jour. Chaque point se veut simple et dédié à une fonctionnalité
unique.
• Premier export
Cette étape est celle que nous avons analyser tout au long de ce mémoire : les données sont
récupérées, traitées, validées et persistées. Ce n’est qu’après toutes ces étapes que notre classe
36
EnsureUpdateData récupère l’ « id 30
» d’insertion du document et le met à jour dans le
champ « mongo_id ». Nous pouvons maintenant assurer la partie mise à jour et suppression des
données.
• Mise à jour
Si, lors du processus d’export, la ligne référencée possède un « ObjectId » ou identifiant
MongoDB, nous basculerons sur un nouveau processus. En effet, en sortie de traitement, les
données à importer (en tant que document) interagissent avec la classe DataExport de manière
à être transformées en JSON, puis persistées. Puisque nous savons qu’il ne s’agit pas, ici, d’un
premier export, nous chargerons plutôt EnsureDataUpdateExport qui a pour vocation de
mettre à jour le document référencé au lieu d’en ajouter un nouveau.
• Suppression
Pour finir, un service CleanIndexAutomat a été déployé. Il implémente nos classes
DataExport pour le premier export et EnsureDataUpdateExport pour une mise à jour. A chaque
appel de ces classes, une analyse comparative intervient dans le but de supprimer d’éventuels
documents n’étant plus référencés sous MySQL. A la fin de ce traitement, nous avons récupéré
une liste de documents solitaires. Une simple requête nous permet de les retirer de la collection
concernée.
Schématisation globale de la mise à jour
30
« id » pour identifiant
37
CONCLUSION
A travers ce mémoire nous avons exploré, étape par étape, le processus de
développement d’une application sur mesure basée sur une problématique liée à mon travail de
tous les jours. La redondance de données est un sujet complexe qui a modifié toute ma façon de
penser ce sujet : l’analyse des besoins et des solutions existantes a été le pivot central dans la
réalisation de ce projet.
Nous possédons maintenant une application fonctionnelle qui répond à toutes nos attentes
dans l’import/export continu, ou, dans la redondance des données. Une étape de réflexions
supplémentaires m’a permis d’analyser la solution que j’ai fournie à la fin du développement :
nous noterons que l’application livrée pourra être améliorée, ou, optimisée de diverses façons.
Pour commencer, j’aimerais parler du processus global d’export de MySQL vers MongoDB.
Je suis réellement satisfait de sa conception et de son développement. Toutefois, certains
process sont à revoir, dans l’objectif principal d’améliorer les performances d’exports à grande
échelle.
Ensuite, le soft étant censé faciliter la vie du développeur, il serait utile de pouvoir ajouter,
au système de traitement des données, des filtres et des processus de vérification d’intégrité
personnalisés. En effet, nous pourrions aisément importer de nouvelles options au fichier de
configuration afin de prendre en compte des méthodes sur mesure, adaptées à la logique de
l’entreprise.
Pour finir, il serait intéressant de développer cette application à des bases de données autres
que MongoDB et MySQL. Même s’ils sont leaders dans leur domaine, d’autres outils existent
et sont aussi populaires : nous retrouvons MariaDB et PostreSQL pour les bases de données
relationnelles, et CouchDB et Riak pour les bases orientées document.
38
ANNEXES
Annexe 1
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Tableau comparatif 31
entre MySQL et MongoDB :
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
31
Source: HACKERNOON https://hackernoon.com/mongodb-vs-mysql-comparison-which-database-is-better-
e714b699c38b
39
Annexe 2
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Relation du deuxième degré, un schéma d’export invalide : Intégration d’un document dans un
document intégré au document source.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
* @EXPORTdocument(table="products")
*/
class Product
{
/**
* @EXPORTeject(document="Fabricant", related="id_fab")
*/
protected $fabricant;
}
/**
* @EXPORTdocument(table="fabricants")
*/
class Fabricant
{
/**
* @EXPORTeject(document="MaisonMere", related="id_house")
*/
protected $maisonMere;
}
/**
* * @EXPORTdocument(table="maisons")
*/
class MaisonMere
{
/**
* @EXPORT
*
*/
protected $name;
}
40
Annexe 3
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Relation du premier degré, un schéma d’export valide : Injection de données dans un document
intégré au document source.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**
* @EXPORTdocument(table="products")
*/
class Product
{
/**
* @EXPORTeject(document="Fabricant", related="id_fab")
*/
protected $fabricant;
}
/**
* @EXPORTdocument(table="fabricants")
*/
class Fabricant
{
/**
* @EXPORTinject(document="MaisonMere", related="id_house" {"name"})
*/
protected $maisonMere;
}
/**
* * @EXPORTdocument(table="maisons")
*/
class MaisonMere
{
/**
* @EXPORT
*
*/
protected $name;
}
41
Annexe 4
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Configuration de docker : docker-compose.yaml
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
version: '2'
services:
### PHP-CLI Container #######################################
php-cli:
image: php:cli
### MySQL Container #########################################
mysql:
build: ./${DOCKER_DIRECTORY}/mysql
ports:
- "${MYSQL_PORT}:3306"
environment:
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
### MongoDB Container #######################################
mongo:
build:
context: ./${DOCKER_DIRECTORY}/mongo
dockerfile: ${MONGODB_DOCKERFILE}
ports:
- "${MONGODB_PORT}:27017"

Contenu connexe

Similaire à Comment assurer la redondance de données d’une base relationnelle vers une base orientée document ?

Création de bases de données
Création de bases de donnéesCréation de bases de données
Création de bases de donnéesRiadh ASSOUAK
 
Journée des correspondants Tice 2013 : support de la journée
Journée des correspondants Tice 2013 : support de la journéeJournée des correspondants Tice 2013 : support de la journée
Journée des correspondants Tice 2013 : support de la journéeDocumentation Rouen
 
Comment le social augment l'accès à l'information
Comment le social augment l'accès à l'informationComment le social augment l'accès à l'information
Comment le social augment l'accès à l'informationLecko
 
Presentation pole-17 dec - v4
Presentation pole-17 dec - v4Presentation pole-17 dec - v4
Presentation pole-17 dec - v4Muriel Milhaud
 
Rapport de stage d'initiation 2015 Mahmoudi Mohamed Amine
Rapport de stage d'initiation 2015 Mahmoudi Mohamed AmineRapport de stage d'initiation 2015 Mahmoudi Mohamed Amine
Rapport de stage d'initiation 2015 Mahmoudi Mohamed AmineMohamed Amine Mahmoudi
 
Capitalisation d'expériences pour l'indexation et la recherche d'information ...
Capitalisation d'expériences pour l'indexation et la recherche d'information ...Capitalisation d'expériences pour l'indexation et la recherche d'information ...
Capitalisation d'expériences pour l'indexation et la recherche d'information ...espenel
 
La technologie Big Data : un outil pour l'optimisation des processus de cons...
 La technologie Big Data : un outil pour l'optimisation des processus de cons... La technologie Big Data : un outil pour l'optimisation des processus de cons...
La technologie Big Data : un outil pour l'optimisation des processus de cons...lucasdenis2000
 
Quel outil pour quel usage ?.pdf
Quel outil pour quel usage ?.pdfQuel outil pour quel usage ?.pdf
Quel outil pour quel usage ?.pdfPhilippeVIGIER5
 
GESTION ELECTRONIQUE DE DOCUMENT
GESTION ELECTRONIQUE DE DOCUMENTGESTION ELECTRONIQUE DE DOCUMENT
GESTION ELECTRONIQUE DE DOCUMENTSerge Wallas
 
Passer à Office 365 ? Vous le saurez dans 7 jours
Passer à Office 365 ? Vous le saurez dans 7 joursPasser à Office 365 ? Vous le saurez dans 7 jours
Passer à Office 365 ? Vous le saurez dans 7 joursMicrosoft Technet France
 
Musette Numérique de l'Actif - livrable final
Musette Numérique de l'Actif - livrable finalMusette Numérique de l'Actif - livrable final
Musette Numérique de l'Actif - livrable finalFing
 
Favoriser la collaboration en entreprise 02-2018
Favoriser la collaboration en entreprise   02-2018Favoriser la collaboration en entreprise   02-2018
Favoriser la collaboration en entreprise 02-2018Philippe Ouellette
 
Interopérabilité des Services Web dans le cadre d’une Architecture SOA
Interopérabilité des Services Web  dans le cadre d’une Architecture SOAInteropérabilité des Services Web  dans le cadre d’une Architecture SOA
Interopérabilité des Services Web dans le cadre d’une Architecture SOAJean Paul Dongmo Miaffo
 
Le web sémantique pour mieux anticiper le futur
Le web sémantique pour mieux anticiper le futurLe web sémantique pour mieux anticiper le futur
Le web sémantique pour mieux anticiper le futurSylvain Gateau
 

Similaire à Comment assurer la redondance de données d’une base relationnelle vers une base orientée document ? (20)

Création de bases de données
Création de bases de donnéesCréation de bases de données
Création de bases de données
 
Journée des correspondants Tice 2013 : support de la journée
Journée des correspondants Tice 2013 : support de la journéeJournée des correspondants Tice 2013 : support de la journée
Journée des correspondants Tice 2013 : support de la journée
 
Intranets230316
Intranets230316Intranets230316
Intranets230316
 
cours edi
cours  edicours  edi
cours edi
 
Comment le social augment l'accès à l'information
Comment le social augment l'accès à l'informationComment le social augment l'accès à l'information
Comment le social augment l'accès à l'information
 
Presentation pole-17 dec - v4
Presentation pole-17 dec - v4Presentation pole-17 dec - v4
Presentation pole-17 dec - v4
 
Rapport de stage d'initiation 2015 Mahmoudi Mohamed Amine
Rapport de stage d'initiation 2015 Mahmoudi Mohamed AmineRapport de stage d'initiation 2015 Mahmoudi Mohamed Amine
Rapport de stage d'initiation 2015 Mahmoudi Mohamed Amine
 
Sujet de thèse : CATCAP
Sujet de thèse : CATCAPSujet de thèse : CATCAP
Sujet de thèse : CATCAP
 
Capitalisation d'expériences pour l'indexation et la recherche d'information ...
Capitalisation d'expériences pour l'indexation et la recherche d'information ...Capitalisation d'expériences pour l'indexation et la recherche d'information ...
Capitalisation d'expériences pour l'indexation et la recherche d'information ...
 
La technologie Big Data : un outil pour l'optimisation des processus de cons...
 La technologie Big Data : un outil pour l'optimisation des processus de cons... La technologie Big Data : un outil pour l'optimisation des processus de cons...
La technologie Big Data : un outil pour l'optimisation des processus de cons...
 
Quel outil pour quel usage ?.pdf
Quel outil pour quel usage ?.pdfQuel outil pour quel usage ?.pdf
Quel outil pour quel usage ?.pdf
 
GESTION ELECTRONIQUE DE DOCUMENT
GESTION ELECTRONIQUE DE DOCUMENTGESTION ELECTRONIQUE DE DOCUMENT
GESTION ELECTRONIQUE DE DOCUMENT
 
Passer à Office 365 ? Vous le saurez dans 7 jours
Passer à Office 365 ? Vous le saurez dans 7 joursPasser à Office 365 ? Vous le saurez dans 7 jours
Passer à Office 365 ? Vous le saurez dans 7 jours
 
Nlle présentation
Nlle présentationNlle présentation
Nlle présentation
 
Intro SQL
Intro SQL Intro SQL
Intro SQL
 
Musette Numérique de l'Actif - livrable final
Musette Numérique de l'Actif - livrable finalMusette Numérique de l'Actif - livrable final
Musette Numérique de l'Actif - livrable final
 
Favoriser la collaboration en entreprise 02-2018
Favoriser la collaboration en entreprise   02-2018Favoriser la collaboration en entreprise   02-2018
Favoriser la collaboration en entreprise 02-2018
 
Lemarchand nadège
Lemarchand nadègeLemarchand nadège
Lemarchand nadège
 
Interopérabilité des Services Web dans le cadre d’une Architecture SOA
Interopérabilité des Services Web  dans le cadre d’une Architecture SOAInteropérabilité des Services Web  dans le cadre d’une Architecture SOA
Interopérabilité des Services Web dans le cadre d’une Architecture SOA
 
Le web sémantique pour mieux anticiper le futur
Le web sémantique pour mieux anticiper le futurLe web sémantique pour mieux anticiper le futur
Le web sémantique pour mieux anticiper le futur
 

Comment assurer la redondance de données d’une base relationnelle vers une base orientée document ?

  • 1. Comment assurer la redondance de données d’une base relationnelle vers une base orientée document ? THOMAS THIEBAUDET 2016-2017
  • 2. 1 SOMMAIRE Sommaire ................................................................................................................................................ 1 Avant propos........................................................................................................................................... 2 Remerciements ....................................................................................................................................... 3 Introduction ............................................................................................................................................ 4 Développement....................................................................................................................................... 7 1. Analyse des solutions existantes................................................................................................. 7 2. Développement d’une application sur mesure......................................................................... 10 2.1. Analyse du besoin ............................................................................................................. 10 2.2. Environnement de développement .................................................................................. 12 3. Conception du système............................................................................................................. 13 3.1. Schématisation des données............................................................................................. 13 3.1.1. Synthétiser l’export via les annotations.................................................................... 13 3.1.2. Préparer la base documentaire................................................................................. 16 3.1.3. Vérification de la configuration................................................................................. 19 3.2. Export des données........................................................................................................... 22 3.2.1. Processus d’import / export...................................................................................... 22 3.2.2. Déclarer les associations ........................................................................................... 24 3.2.3. Gérer les associations................................................................................................ 27 3.2.4. Ajouter des filtres...................................................................................................... 31 3.2.5. Assurer l’intégrité de données sensibles................................................................... 33 3.3. Mise à jour des données ................................................................................................... 35 Conclusion............................................................................................................................................. 37 Annexes................................................................................................................................................. 38
  • 3. 2 AVANT-PROPOS Développeur web passionné, je me suis formé dans un premier temps et depuis mon plus jeune âge de manière autodidacte au développement. C’est en 2014, lorsque les chemins de ma vie me l’ont permis, que j’ai intégré une première formation de niveau Bac + 2 à l’AFPA de Chevigny St-Sauveur (21). J’ai également pu effectuer, durant ce temps d’apprentissage, un stage de trois mois chez MB Salon afin d’y développer un back-office dédié à l’administration de l’entreprise. Fort de cette expérience, j’ai par la suite intégré le Mastère 1 - Développement Web Et Mobile de l’école IPSSI de Paris XIIème. Aujourd’hui, arrivé au seuil du terme de ce Mastère 1, j’ai le plaisir de mener à bien un travail de mémoire technique, fruit de cette formation de deux ans et qui, je le souhaite, saura refléter au mieux l’enrichissement professionnel que m’ont apporté ces deux dernières années. De plus, je travaille actuellement pour l’entreprise Aerocontact, premier réseau professionnel aéronautique et spatial. Aerocontact, en pleine expansion, dispose d’un portail dédié, spécialisé dans l’actualité mais également dans l’emploi de l’industrie aéronautique, spatiale et de la défense. C’est dans cette entreprise que j’ai rapidement pris conscience de l’importance des bases de données et surtout de leur utilisation. C’est pourquoi j’ai souhaité me consacrer à ce sujet dans ce mémoire technique, qui s’intéresse aux solutions permettant d’assurer la redondance de données d’une base relationnelle vers une base orientée document.
  • 4. 3 REMERCIEMENTS J’adresse mes plus sincères remerciements à toutes celles et tous ceux qui, par leur soutien et leur contribution, m’ont permis d’élaborer ce mémoire. Je souhaite en premier lieu remercier l’ensemble de l’équipe de l’entreprise Aerocontact et en particulier M. Fréderic Vergoz, mon employeur, avec qui j’ai construit une relation de confiance et de partage et qui a su m’apporter soutien et encouragements depuis le début de ma formation. Je remercie également mon collègue Renaud Fayolle, pour son aide précieuse et les grandes compétences techniques qui sont les siennes et qu’il a généreusement mis à mon service dans mon activité professionnelle. Merci à l’école IPSSI, qui m’a donné l’opportunité d’intégrer une formation de qualité, enrichissante tant dans les cours qu’elle dispense que grâce aux relations professionnelles qu’elle m’a permis d’établir. Mes remerciements les plus affectueux à Muriel, secrétaire à l’IPSSI, pour sa gentillesse et son sourire de tous les jours. Je souhaite également adresser mes sincères remerciements à mes collègues de formation pour leur soutien sans faille et pour l’enrichissement tant personnel que professionnel qu’ils ont pu m’apporter, par les liens que nous entretenons comme par les croisements de compétences qui en résultent. Mes remerciements tout particuliers à deux d’entre eux, Anthony Lemprière et Nicolas Grévin, pour avoir offert le gîte au Bisontin que je suis lors des semaines de formation. Merci enfin à mon compagnon, pour son aide précieuse dans l’étape de relecture de ce mémoire.
  • 5. 4 INTRODUCTION La genèse de ce mémoire repose sur un tout premier questionnement : quels sont les avantages de la redondance d’informations d’une base à une autre ? Premièrement, la redondance de données entre le back-office1 et le front-office permet d’avoir deux environnements compartimentés et dédiés. Le back-office s’occupe de gérer et d’administrer les données et le front-office2 n’a plus qu’à lire des données générées pour son seul usage. Ce « cloisonnement de données » ou « division de données » assure une sécurité renforcée et une meilleure répartition dans les ressources liées à l’utilisation des bases de données. Deuxièmement, on retrouve communément sur des bases relationnelles âgées des problèmes d’intégrité de données dus à des modifications, à de nouvelles versions ou un travail hétérogène exécuté par plusieurs développeurs et ce sur une longue période. Parfois, il arrive que certains des résultats issus de ces bases soient incohérents et porteurs de bogues et donc préjudiciables pour une entreprise. Troisièmement, et pour finir, le fait de réaliser cet audit dans le but d’exporter des données vers une base dédiée à lecture est la toute première étape, mais importante, ayant pour objectif de clarifier ses bases de données actuelles. Définir des contraintes d’intégrité, des formats de données, et même de logique, permet une meilleure appréhension des problématiques liées au grand univers de la base de données. De ce constat est né le questionnement qui guidera notre réflexion et nos propositions de solutions. Ce questionnement est le suivant : Comment assurer la redondance de données d’une base relationnelle vers une base documentaire ? 1 Une application de back office est la partie d'un système informatique qui n'est pas accessible aux utilisateurs finaux ou aux clients. 2 Une application de front office ou logiciel de front office est la partie d'un système informatique accessible aux utilisateurs finaux ou aux clients.
  • 6. 5 Tout d’abord, il est nécessaire de définir les termes techniques et syntaxiques de cette problématique : « redondance », « base relationnelle », « base documentaire », et la préposition « vers », qui prend ici tout son sens. Le terme de « redondance » renvoie au fait de répéter plusieurs fois la même chose : une donnée « x » serait donc redondée en une donnée « y » une ou plusieurs fois. La redondance implique donc au moins un point de départ et un à plusieurs points de destination. Dans la langue française, le terme de redondance renvoie aux notions de l’inutile et du superflu. Je montrerai au cours de ce mémoire que dans le domaine du développement web et de l’univers du stockage de données, la redondance revêt un tout autre aspect. D’autre part, nous avons d’un côté une base relationnelle et de l’autre une base documentaire. Par définition la base de données est « un outil permettant de stocker et de retrouver l'intégralité des données brutes en rapport avec un thème ou une activité ». En quoi ces deux bases sont-elles différentes ? La base de données relationnelles est un système qui a fait ses preuves depuis les années 1970, tandis que la base orientée document est beaucoup plus récente. C’est pour cela que la majorité des bases de données conçues avant 2010 sont stockées avec un schéma relationnel. De nos jours, ces bases sont créées et utilisées pour du traitement de données et donc affiliées, par définition, à un back-office par exemple, mais sont encore très utilisées. La base de données documentaire ou orientée document a un tout autre rôle. Grâce à de nouvelles caractéristiques, différentes de la base de données relationnelle, elle nous permet la définition de schémas de données dynamiques et même une capacité de lecture plus performante. C’est donc pour ces raisons, et bien d’autres non citées (Cf Annexe 1), que la base de données documentaire est très souvent utilisée pour sa capacité de lecture améliorée, dans ce que l’on appelle le front-office. Dans ma problématique et entre les deux occurrences des termes « base relationnelle » et « base documentaire », nous retrouvons le mot « vers », préposition indiquant un mouvement. De ce fait nous avons bien un point « x », base de données relationnelle et un point « y », base de données documentaire. C’est l’action de ce point vers l’autre qui définit la notion même de redondance. Nous souhaitons exporter les données de « x » à « y ».
  • 7. 6 Afin de répondre et de trouver des solutions au questionnement qui nous occupe, nous analyserons dans un premier temps quelles sont les solutions déjà existantes ; pour, dans une seconde et dernière partie, nous intéresser à la schématisation et à l’export des données dans le cadre du développement de cette application sur mesure.
  • 8. 7 DEVELOPPEMENT 1. Analyse des solutions existantes Plusieurs outils existent actuellement et sont disponibles afin de répondre, plus ou moins bien, à notre problématique : assurer la redondance de données d’une base SQL3 à une base NoSQL4 . Durant ma phase de recherches, j’ai pu relever trois solutions sérieuses. J’ai tenté de les examiner en détail afin de vérifier qu’elles soient réellement adaptées à nos besoins. Voyons ensemble, et une à une, si ces solutions sont à envisager. • Solution numéro 1 : Utiliser le format CSV5 Le premier choix que nous avons est d’exporter notre base de données MySQL, table par table, au format CSV, avant de l’importer dans notre base MongoDB. En effet, l’aspect simplissime du document texte .csv le rend interprétable par notre SGBD document. Malheureusement, même si ce procédé nous assure une mise en place rapide, nous devons pallier à plusieurs problèmes. En effet, cette solution ne gère pas les relations et ne vérifie pas l’intégrité des données à exporter. Compte tenu de ces difficultés, nous n’irons pas plus loin dans l’examen de cette solution. LES PLUS LES MOINS Compatible MySQL / MongoDB Ne gère pas les relations Mise en place rapide Ne vérifie pas l’intégrité avant export 3 Le SQL (Structured Query Language) est un langage permettant de communiquer avec une base de données. 4 NoSQL désigne une famille de systèmes de gestion de bases de données (SGBD) qui s'écarte du paradigme classique des bases relationnelles. 5 « Comma-separated values », connu sous le sigle CSV, est un format informatique ouvert représentant des données tabulaires sous forme de valeurs séparées par des virgules.
  • 9. 8 • Solution numéro 2 : Créer un script sur mesure Le deuxième choix qui s’offre à nous est de scripter un ensemble de procédures afin d’exporter l’ensemble de nos données. C’est-à-dire réaliser un code PHP qui exportera, table par table, colonne par colonne, élément par élément, les données qui nous intéressent. Cette solution a le mérite d’être sur mesure et est donc adaptée à notre projet. Malheureusement, c’est une méthode fastidieuse qui ne sera pas déployable rapidement. Le code ne pourra pas être réutilisé et nous devrons redévelopper de nouveaux scripts pour assurer la mise à jour des données dans le temps. LES PLUS LES MOINS Sur mesure et donc adapté à notre projet Fastidieux à mettre en place Possibilité de traitement sur les données N’assure pas la mise à jour des données Code non réutilisable • Solution numéro 3 : Mongify (1.3.2) Cette dernière solution est une application, développée en RUBY6 , qui a pour vocation d’assurer l’import de nos données relationnelles vers MongoDB. Mongify est utilisable uniquement en ligne de commande et permet de créer des schémas de données à exporter. De plus, nous devons fournir des fichiers de configurations en RUBY. Mongify gère les relations du premier degré dans l’import des données et assure l’intégration de documents. Malheureusement, quelques points négatifs sont à noter : la vérification de l’intégrité des données est faible avec Mongify. En effet, seule la vérification concernant le type de données est disponible, et c’est un point définitivement bloquant pour notre projet actuel. De plus, son système de fonctionnement n’assure pas la mise à jour des données, mais seulement l’export et l’import. En utilisant Mongify, et dans l’objectif de mettre à jour mes données, je serai forcé de supprimer les données actuelles de MongoDB avant de renouveler l’import. Cette méthode 6 Ruby est un langage de programmation libre, interprété et orienté objet.
  • 10. 9 n’est donc pas optimisée pour assurer la redondance de données de manière continue. On notera également que l’injection de documents n’est pas non plus disponible dans sa version actuelle. LES PLUS LES MOINS Gère les relations du premier degré N’assure pas la mise à jour des données Utilisation simplifiée en ligne de commande Beaucoup de configuration à renseigner Vérification faible de l’intégrité des données Après cette inspection des outils disponibles, j’ai choisi de totalement ignorer l’utilisation des documents CSV pour assurer la redondance de données que je recherche. Pour ce qui est des solutions numéro deux et numéro trois, elles ne correspondent que partiellement à mon projet. Toutefois elles m’ont aidé dans le choix d’une solution sûre. J’ai donc choisi de « fusionner », en quelques sortes, ces deux dernières solutions de manière à réutiliser l’ensemble de leurs avantages et de pallier à leurs inconvénients. A travers ce mémoire, nous verrons les étapes nécessaires afin de concevoir, puis développer, une application sur mesure nous permettant d’assurer la redondance de données d’une base relationnelle vers une base orientée document. Commençons, dès maintenant, l’analyse précise de nos besoins à travers ce deuxième chapitre.
  • 11. 10 2. Développement d’une application sur mesure 2.1. Analyse du besoin A travers cette analyse du besoin, nous allons répertorier ici, l’ensemble des fonctionnalités nécessaires à notre application. Chaque point référencé possèdera au moins un chapitre lui étant entièrement dédié. Tout d’abord, nous souhaitons que notre application soit simple d’utilisation. Ce soft n’ayant pas besoin d’un navigateur, nous aurons besoin d’utiliser notre terminal. Nous aborderons ce point dans le chapitre « Synthétiser l’export via les annotations » où nous trouverons, dans ces « annotations », une aide quasi-indispensable. Ensuite, nous souhaitons avoir le moins possible de configurations. Plus que ça, nous souhaitons également pouvoir nous assurer que la configuration donnée soit bien valide. Ces deux besoins seront détaillés dans les chapitres « Préparer la base documentaire » et « Vérification de la configuration ». Nous aurons vraisemblablement besoin d’exporter des données de MySQL et de les importer dans MongoDB. Pour assurer cette fonctionnalité essentielle, nous approfondirons le sujet, point par point, dans un chapitre propre à la redondance de données : « Processus d’import / export ». Indispensable à nos besoins, nous souhaitons, de manière optimisée, nous occuper de la gestion des relations. Nous désirons également que cette capacité à assurer les associations soit facilement paramétrable. Ces deux parties seront analysées dans « Déclarer les associations » et « Gérer les associations ». Les données que nous devrons traiter ne sont pas homogènes dans leurs formats car elles ont été altérées durant plus d’une décennie. La transformation de ces données, grâce aux filtres, solutionnera cette préoccupation dans le chapitre « Ajouter des filtres ». L’altération continue de ces données peut provoquer plus que des problèmes de format. Certaines données, telles que les clés primaires et clés étrangères, non valides, sont considérées comme non-intègres et donc problématiques pour notre application. Ces données, non intègres, sont problématiques pour l’état de santé général de notre soft. En effet, elles sont porteuses de
  • 12. 11 bogues potentiellement nuisibles. Nous examinerons ce désagrément dans « Assurer l’intégrité de données sensibles ». Pour finir, dans le chapitre « Mise à jour des données », nous passerons en revue les étapes nécessaires à la mise à jour des données de manière à assurer une redondance continue des données. Ces besoins étant établis, attelons-nous maintenant au développement de cette application sur mesure. En trois parties nous aborderons, premièrement, la schématisation des données ou méta-données. Nous verrons ensuite le fonctionnement du processus d’import/export à travers différentes sous-catégories. Enfin nous parcourrons les étapes de mise à jour.
  • 13. 12 2.2. Environnement de développement Par habitude, j’ai utilisé PHPSTORM comme IDE7 ; mais par besoin, j’ai développé cette application sous linux. En effet, Docker8 a été le moteur central de mon environnement de développement et n’est pleinement fonctionnel que sous linux. J’ai conçu cet environnement de développement en trois conteneurs distincts : PHP-CLI, MySQL et MongoDB. Le premier conteneur exploitera PHP en lignes de commande, et MySQL et MongoDB émulerons des serveurs de base de données. Vous pourrez retrouver la configuration du docker-compose.yaml dans les annexes de ce mémoire. Par ailleurs, voici une liste non-exhaustive des librairies importées à notre application : - doctrine/orm - cocur/slugify - gedmo/doctrine-extensions - symfony/validator - jdorn/sql-formatter Nous étudierons de plus près MongoDB et installerons sa version 3.2 : des nouvelles fonctionnalités ont fait leur apparition. L’une d’entre elles, considérable, est la validation des documents avant persistance des données. Concernant MySQL, nous utiliserons sa dernière version stable, qui date de 2013 : la 5.6. C’est celle qui est actuellement utilisée sur nos serveurs d’entreprise et qui nous assure une compatibilité avec cette nouvelle application. Pour visualiser le contenu des bases de données, durant notre phase de test, nous installerons deux SGBD9 : « MongoDB Compass » pour visualiser nos données stockées sous MongoDB et « phpMyAdmin » sous MySQL. 7 « integrated development environment » Un environnement de développement est un ensemble d'outils pour augmenter la productivité des programmeurs qui développent des logiciels. 8 Docker est un logiciel libre qui automatise le déploiement d'applications dans des conteneurs logiciels. 9 « Système de gestion de base de données »
  • 14. 13 3. Conception du système 3.1. Schématisation des données 3.1.1. Synthétiser l’export via les annotations Avant toute chose, il est important de rappeler que l’annotation est un élément qui permet l’ajout de méta-données à une classe, un attribut, des fonctions etc. Depuis la croissance de popularité des frameworks PHP tels que Symfony ou Laravel, pour n’en citer que deux, on trouve des annotations dans la plupart des fichiers PHP. Ces annotations sont utilisées pour documenter le code de façon générale. On retrouve des indications sur la dépréciation d’éléments et de fonctions et parfois une aide dans l’utilisation des méthodes présentes. Leur utilisation est très appréciée des développeurs tant dans l’emploi du code que dans la conception de système divers. Dans le cadre du développement de la solution de redondance de données, les annotations m’ont permis un gain de temps non négligeable dans l’élaboration de mon application qui s’explique pour deux raisons : la malléabilité et la réutilisation d’annotations existantes. En effet, la souplesse dans la création de méta-données est considérable. J’ai pu élaborer une syntaxe simple et adaptée à mes besoins dans une utilisation quotidienne de l’application. Utiliser des annotations existantes a simplifié ma phase de développement. Sur la base du framework Symfony, j’ai pu réutiliser, sans encombre, certains des éléments de la classe SymfonyComponentValidatorConstraints, généralement appelée « Assert 10 », dans la gestion des contraintes d’export. La librairie de Doctrine11 est également riche en ressources indispensables pour mes besoins en récupération d’informations relatives aux bases de données : index, appellation, type, relation… S’il est simple d’ajouter des méta-données, par exemple à un modèle, il est également aisé d’en récupérer les informations. On appelle cela, dans notre cas, une analyse de classe. 10 « Faire valoir ». 11 « Doctrine » est une couche d’abstraction à la base de données.
  • 15. 14 Depuis les débuts de PHP, dans ses premières versions, il était beaucoup plus compliqué d’analyser son code en lui-même. D’ailleurs l’ajout de la PHP DOC12 n’a eu lieu que vers les années 2000. Mais c’est avec PHP en version 5, et plus précisément la version 5.1 de 2005, qu’apparut une classe actuellement très populaire : ReflectionClass. C’est grâce à elle, en grande partie, qu’ont vu le jour les premières applications à implémenter un « moteur », destinées à tirer le meilleur parti d’une classe : l’analyse des méta- données pour en extraire des informations ; c’est pourquoi je l’ai utilisée dans le développement de mon application. D’un point de vue technique, dans la récupération de ces méta-données, j’ai pu répartir le processus d’analyse en trois classes : ModelClassParser, ModelAttributesParser et ModelFunctionsParser. ModelClassParser se charge d’analyser les annotations spécifiques à une classe, situées au-dessus de la déclaration de cette dernière. On trouvera des informations concernant l’export de la table sous MySQL annotées au document. /** * @EXPORTdocument(table="users_3", document="users") */ class User {} ModelAttributesParser s’occupera de la récupération des méta-données associées aux attributs de notre entité. C’est ici que nous pourrons filtrer à l’export nos données en modifiant leur contenu ou en assurant leur intégrité et les contraintes avant l’import dans leur document de destination. /** * @EXPORTfilter("upper") * @EXPORTintegrity(unique=true, format="dw") */ protected $reference; 12 Standard formalisé pour commenter le code PHP.
  • 16. 15 ModelFunctionsParser a été créé, mais n’est pas encore implémenté dans mon application. En effet, je n’ai pas trouvé d’utilité à annoter des méthodes dans mon cas ; bien que dans une version d’amélioration et d’optimisation de ce soft, il serait intéressant d’utiliser des filtres personnalisés d’export avec un système d’annotation de fonctions. Ce processus d’analyse va pouvoir alors générer un fichier de configuration spécifique pour chaque modèle annoté. L’ensemble de ces fichiers sera importé au manifeste : notre fichier de configuration générale.
  • 17. 16 3.1.2. Préparer la base documentaire L’étape de synthétisation de notre classe étant terminée, nous allons pouvoir définir les informations essentielles à l’export de notre base de données relationnelle vers notre nouvelle base documentaire. Quels sont les éléments indispensables pour assurer notre redondance de données ? Tout d’abord, il nous faut connaître l’actuelle configuration de la base de données à extraire. Mais il est également nécessaire de définir un nouveau schéma sur notre base de données documentaire. Dans le but d’importer de nouvelles données filtrées, triées, intègres, il est indispensable d’associer également à ce manifeste l’ensemble des modèles annotés. Ce fichier « manifesto » est structuré en YAML13 , tout d’abord car sa structure fait que son contenu est facilement lisible pour un humain, mais aussi parce que plusieurs librairies PHP sont proposées pour gérer ce format. • Configuration d’une base MySQL On a besoin, premièrement, du nom de la base à exporter et des informations de connexion ainsi que d’éléments pour assurer la mise à jour des données après un export réussi. Pour la connexion, nous trouvons le nom d’hôte, le nom d’utilisateur, le mot de passe, le port et le « charset14 » pour en définir l’encodage des données. Pour assurer la mise à jour des lignes en documents, nous aurons besoin d’un point de référence sur chaque table dans notre base hôte. Une fois ces options indexées dans notre fichier de configuration, nous devrons rajouter une nouvelle colonne dans nos tables représentées par nos modèles annotés. Nous reprendrons le même nom que notre manifesto.yaml et définirons cette colonne comme étant de type « VARCHAR », avec une taille maximale de 24 caractères (correspondant à la taille l’ObjectId15 de notre document MongoDB). L’essentiel des données primaires étant enfin défini pour assurer l’export, nous pouvons maintenant recenser les éléments garantissant l’import vers notre base documentaire. 13 Acronyme de « Yet Another Markup Language » YAML est un format de représentation de données par sérialisation Unicode. 14 Jeux de caractères codés. 15 Classe qu’utilise MongoDB pour générer des identifiants de 12-byte
  • 18. 17 • Configuration d’une base MongoDB Pour connecter notre base documentaire, nous aurons besoin des mêmes informations de connexion : le nom d’hôte, le nom d’utilisateur, le mot de passe et le port. Par défaut, le nom de la base de données sera identique à celle de MySQL. Toutefois, une option permettra d’en assurer la personnalisation. Certaines options doivent être intégrées dans la création de nouvelles collections. Si elles ne sont pas renseignées, elles conserveront leur valeur par défaut. Il s’agit du nombre maximum de documents pouvant être contenus par une collection et de sa taille maximale. Il était très important d’assurer l’intégrité des données durant l’export car, je le rappelle, cette solution est adaptée aux bases de données destructurées souhaitant disposer d’une base de données documentaire claire, saine et intègre. Par conséquent, j’ai intégré deux options de configurations associées aux collections ayant pour but de valider un document lors de sa persistance et de sa mise à jour : validationLevel et validationAction. - validationLevel permet de gérer le degré de validation à appliquer avant d’enregistrer un document. Il peut être désactivé (off), modérément appliqué (moderate) ou très exigeant (strict). - validationAction rajoute une couche de sécurité en permettant de générer, en fonction des conditions de validation, un code d’erreur qui stoppe l’insertion ou bien un code d’avertissement permettant de log durant l’import des données vers MongoDB. En réalité, ces options de configuration sont directement reliées aux annotations de modèles assurant l’intégrité des données, et seront expliquées plus en aval (cf partie 3.2.4). Pour schématiser cette préparation « d’export/import » de données ou de redondance de données, voici un aperçu du fichier de configuration défini en fonction de nos besoins. # manifesto.conf connection: - mysql: db_name: "monsite" hostname: "hostname.mysql.com" port: 3306 user: "userMysql" password: "p@ssMysql" charset: "" - mongo:
  • 19. 18 db_name: ~ hostname: "hostname.mongo.com" port: 27018 user: "userMongo" password: "p@ssMongo" export: update_on: "mongo_id" import: init: max_doc_size: ~ max_doc_count: ~ validation: level: "strict" action: "warning" imports: ['user']
  • 20. 19 3.1.3. Vérification de la configuration Pour assurer le bon fonctionnement de notre configuration, trois points essentiels sont à vérifier : - La connexion MongoDB est-elle fonctionnelle ? - La connexion MySQL est-elle fonctionnelle ? - Les modèles importés sont-ils valides ? - Le fichier de configuration est-il valide ? Tout d’abord, vérifier le fichier de configuration semble être la première étape à réaliser. En effet, toutes les autres vérifications dépendent de ce manifeste. On contrôle en premier lieu si le fichier peut être « parser 16 » ; puis, si l’ensemble des informations récupérées par la classe ManifestoParser est intègre avec ce que nous attendons. Cette classe d’analyse du fichier de configuration est similaire aux classes créées précédemment pour parser les annotations des modèles, à la simple différence que celle-ci utilise des librairies spécifiques à l’analyse du format YAML. Le but de cette dernière est de recenser chaque information sur l’import et l’export afin de construire un objet appelé ExportConfigurator qui contiendra l’intégralité des données de configuration. La classe ValidatorConfigurator, elle, interrogera l’objet ExportConfigurator pour vérifier le format et le contenu des données collectées durant le processus d’analyse du manifeste. 16 « Analyser »
  • 21. 20 Schéma du processus de validations du fichier de configuration La même technique de validation a été déployée pour vérifier les modèles et ses méta- données. Les classes ModelAttributesParser et ModelClassParser génèrent, par un procédé identique, un objet AnnotatorConfigurator ayant pour but d’être consulté par une nouvelle classe : ValidatorAnnotator. Cette dernière s’occupera de vérifier que les annotations recueillies sont bien valides et compréhensibles par notre application. La validation doit bien sûr s’exécuter pour autant de modèles qu’il y a d’importés.
  • 22. 21 Schéma du processus de validations des modèles annotés Pour répondre à la problématique de vérification avec MySQL et MongoDB, il suffit d’utiliser la méthode getConnection du manager de doctrine et en y associant bien sûr les identifiants des deux connexions avec le fichier manifesto.yaml. Un script simple nous permet de faire un appel aux deux bases et de retourner un état pour chacune d’elle. Comment rendre ces étapes de vérifications simples et rapides ? En tant que futur utilisateur de ce soft, je souhaite pouvoir vérifier de façon automatique si la configuration est fonctionnelle, sans avoir à vérifier manuellement tous mes fichiers. La solution la plus pratique que j’ai trouvée est de scripter, étape par étape, les actions nécessaires avant toute utilisation future de l’application. A la mode du PHP en ligne de commande et parce que l’ensemble de mon programme tourne sous PHP, j’ai décidé de créer un fichier effectuant les vérifications nécessaires en différentes procédures, avant de retourner au terminal un code d’erreur ou un message de succès. Pour vérifier l’intégrité de la configuration avant l’export, la commande suivante est maintenant disponible pour nous décharger dans l’inspection du code et des différents fichiers : php verification.php
  • 23. 22 3.2. Export des données 3.2.1. Processus d’import / export Pour bien comprendre le fonctionnement de l’application et l’import/export de données, il est important d’avoir au préalable une vision d’ensemble. Voici un schéma simple qui nous permettra d’y voir plus clair. Schématisation du système d’import / export Deux classes, ConnectImport et ConnectExport, interrogent les deux configurateurs dans l’objectif d’assurer une connexion pour l’import avec MySQL et pour l’export avec MongoDB. La classe DataImport s’occupe de générer une requête personnalisée afin de récupérer les données associées à notre modèle. Cette dernière communique avec le système de traitement et de gestion des relations, de manière à collecter les filtres annotés à la classe. Cette personnalisation nous permettra d’ajouter des conditions supplémentaires avant de récupérer des lignes de données. Par exemple, on pourra filtrer les produits et n’exporter que ceux qui se trouvent en stock. Les notions qui concernent les filtres de classe et d’attributs seront abordées dans un chapitre dédié à ce seul sujet (cf. partie 3.2.4 - Ajouter des filtres).
  • 24. 23 Le système de traitement des données est un ensemble de classes qui sont dédiées à accomplir une tâche spécifique. On retrouvera des classes assurant l’intégrité des données, les filtres vus précédemment et la gestion des différents types de relations. La classe DataExport s’occupera, comme son nom l’indique, de l’export des données de notre base relationnelle à notre base orientée document. Cette dernière prendra en paramètre notre requête d’insertion formatée en JSON17 . A cette étape de notre processus d’export, les données ont été filtrées et les relations ont été gérées. Mais les données ne seront considérées comme intègres qu’après leur propre persistance sous forme de documents. En effet, MongoDB dispose d’un système de validation natif depuis sa version 3.2 et nous permettra, par des règles de validations, également formatées en JSON, de persister, ou non, nos données. Processus de persistance des données 17 JSON est un format de données textuelles.
  • 25. 24 3.2.2. Déclarer les associations Bien que MongoDB soit une base orientée document, son mode de fonctionnement permet nativement la gestion d’associations. Les « relations » de MySQL sont appelées « Embedded Documents18 » dans l’univers de MongoDB. L’utilisation des associations est donc possible mais doit se faire avec parcimonie car notre base documentaire n’a pas été conçue pour être performante dans la gestion relationnelle. Alors comment intégrer de façon adéquate certaines relations à notre document durant sa phase d’export ? Demandons-nous si les données contenues dans la relation sont utiles pour notre front-office. Si cette première interrogation penche vers positif, alors nous devrons effectivement insérer ces nouvelles données à notre document, mais pas de n’importe quelle façon. • Intégrer l’ensemble des données jointes dans notre document Prenons un exemple simple : j’ai un modèle Product avec une référence. Ce produit possède une relation « one to many19 » avec Category, ce qui signifie que pour un produit nous aurons zéro à une catégorie ; et, à l’inverse, que pour une même catégorie, nous aurons un à plusieurs produits associés. Dans ce cas, il n’est pas nécessaire de créer un nouveau modèle pour Category mais d’en injecter les données. Pour gérer l’import des catégories dans notre modèle Product, nous devons ajouter de nouvelles annotations, de façon à déclarer qu’il s’agit d’un document à injecter, mais aussi de définir quels éléments sont à importer. /** * @EXPORTinject(document="Categories", related="id_cat" {"name", "description"}) * @EXPORTcolumn("categories_id") */ protected $categories; 18 « Documents intégrés » 19 « Un à plusieurs »
  • 26. 25 La relation est configurée grâce aux méta-données « related 20 » des annotations EXPORTinject et EXPORTcolumn. La première annotation fait référence à l’identifiant unique de notre catégorie, de manière à pouvoir assurer la liaison entre un produit et une catégorie. La deuxième annotation, elle, fait référence au nom de la colonne vers laquelle pointe l’attribut « categories ». Maintenant que nous avons déclaré l’injection des données « name » et « description » à notre produit, nous terminerons par annoter notre modèle Category, de manière à connaître sa table de référence dans notre base relationnelle. /** * @EXPORTdocument(table="categories") */ class Category { } • Créer un nouveau document et le référencer dans notre document actuel Pour rappel, cette technique de « Embedded Documents » n’est pas à utiliser à la légère. Les performances de lecture sur notre front-office ne seront pas optimales. En effet, plutôt que de charger un seul document, MongoDB devra en charger deux en effectuant du traitement supplémentaire pour récupérer ce deuxième document. Toutefois, certaines contraintes, liées à l’entreprise par exemple, ne nous permettent pas d’intégrer de façon brute les éléments dans notre unique modèle et cette technique reste la seule solution pour référencer un modèle externe. Déclarer ce type d’association reste aussi simple que dans le cas précédant. Nous utiliserons l’annotation EXPORTeject pour déclarer notre modèle à intégrer, mais nous n’aurons plus besoin de définir les attributs de Category. /** * @EXPORTeject(document="Categories", related="id_cat") * @EXPORTcolumn("categories_id") */ protected $categories; 20 « Lié à »
  • 27. 26 Occupons-nous pour finir de configurer notre classe Category. Comme plus tôt, nous devons annoter à cette dernière des informations de correspondance à sa table MySQL. Nous en profiterons également pour exporter les attributs « name » et « description », sans vérifier leur intégrité et sans leur ajouter de filtres. /** * @EXPORTdocument(table="categories") */ class Category { /** * @EXPORT */ protected $name; /** * @EXPORT */ protected $description; } L’essentiel des informations permettant de déclarer les relations a bien été communiqué. Il nous faudrait maintenant nous intéresser à la manière dont sont gérés ces deux types de relations.
  • 28. 27 3.2.3. Gérer les associations Nous venons de synthétiser nos associations selon deux schémas type : les documents intégrés et les documents injectés. La partie « annotation » étant terminée, voyons maintenant, et en deux parties, comment sont gérées ces relations. • Injection de documents Rappelez-vous, injecter un document signifie l’intégrer de façon brute dans notre document actuel. C’est la méthode la plus performante et celle à utiliser en priorité afin d’exploiter au maximum le potentiel de MongoDB. Dans notre système de traitement de données, nous retrouvons toutes les classes utilisées pour développer cette gestion des relations. Une classe un peu plus spécifique, InjectDocumentData, se démarque des autres. Elle est le maillon solide du gestionnaire de relation dans l’injection des données d’un document. D’un point de vue technique, cette classe rentre en action dès la fin des opérations de DataImport. En reprenant notre exemple avec le modèle Product, et à ce stade, nous aurions accès à une liste de produits à exporter. Si, et seulement si, le modèle dispose de contraintes relationnelles, la classe InjectDocumentData sera instanciée21 . Grâce aux méta-données fournies dans notre modèle : (nom du document externe, clé(s) primaire(s) et secondaire(s), données à extraire) nous pouvons facilement de là, générer une nouvelle requête avec ces informations et l’aide de notre classe ConnectImport. Les données récupérées sont ajoutées dans un tableau ayant comme index le nom de l’attribut annoté et sont traduites en JSON. Ces nouvelles données brutes sont ensuite injectées au document actuel pour en assurer la lecture. A l’heure actuelle, cette application, ne prend pas en compte les options de filtres et d’intégrités dans la gestion des injections de documents. 21 « Initialiser à partir d’un espace mémoire réservé »
  • 29. 28 • Intégration de documents Techniquement, je dirais que cette gestion d’association automatisée a été la plus complexe à traiter et même à appréhender. J’ai toutefois réussi à exploiter une solution que je vais vous exposer. Conjointement à cette démonstration, seront bien sûr présentées les imperfections que j’ai pu relever durant la phase de développement. La classe EmbeddedDocumentData fait également partie de l’ensemble du système de traitement, au côté de InjectDocumentData. Plutôt que de requêter de nouvelles données à injecter, cette classe, une fois instanciée, va stopper le processus actuel pour exécuter pleinement l’ensemble des tâches qui lui ont été assignées et qui la caractérisent : créer un deuxième document et ajouter un pointeur sur le document actuel. Plutôt que d’injecter des données et de persister notre document, nous devrons passer par plusieurs étapes obligatoires : - Créer un nouveau document - Ajouter ses filtres - Assurer son intégrité - Sauvegarder le pointeur vers ce nouveau document - Reprendre le processus initialement stoppé par EmbeddedDocumentData - Persister le document source Toutes ces étapes se ressemblent et sont répétitives entre le document source et le document à intégrer. De plus, l’échec d’une des étapes est préjudiciable pour le reste des opérations à venir. Voici la première critique négative qui s’est dégagée de mon analyse dans cette gestion des relations. Malheureusement je n’ai pas pu, à l’heure actuelle, optimiser cette partie de développement.
  • 30. 29 Comme vous l’avez remarqué, intégrer un nouveau document revient à reproduire le comportement de la classe DataImport et de son système de traitement, et ce, à l’intérieur de l’instance courante. Notre code est donc réutilisé à travers l’intégration de ce nouveau document. Je relève tout de même cette fois une critique positive dans ce développement : leq processus de création d’un document source et d’un document intégré étant identiques, il nous assure une meilleure évolutivité de l’application et des contraintes similaires dans les étapes de construction de notre document. Pour finir ce dernier point sur les relations, j’aimerais signaler que je me suis limité dans la gestion des intégrations de documents intégrés dans un document intégré, depuis un document source. C’est-à-dire que nous avons un « produit » qui possède une relation avec un « fabricant ». Ce même fabricant possède une relation avec une « maison-mère ». « Maison- mère » est une relation du deuxième degré pour notre produit. Dans le cas où nous souhaiterions intégrer le document « maison-mère » dans le document « fabriquant », et ce document « fabriquant » dans notre document source « produit », nous serions bloqués par l’application. La raison pour laquelle je n’accepte qu’un degré de relation dans la gestion de documents intégrés est simple et a déjà été explicitée : MongoDB est orienté document et n’est pas adapté à la gestion des relations, ou « Embedded Documents ». (Cf. Annexes) Schématisation d’une relation du troisième degré non valide Cependant, rien ne nous en empêchera d’injecter le document « maison-mère », dans le document « fabriquant », et d’intégrer ce dernier document dans le document source « produit ». En effet, l’injection de document ne stoppe pas le processus actuel, à l’inverse des
  • 31. 30 intégrations. Pour rappel, l’injection de document, représentée par InjectDocumentData, ne fait que requêter et insère des données brutes. Pour schématiser cette représentation, nous utiliserons pour cela les annotations dans trois documents séparés. (Cf. Annexes) Schématisation d’une relation de deuxième degré valide
  • 32. 31 3.2.4. Ajouter des filtres Durant la phase de traitement des données, l’ajout de filtres constitue une étape importante dans l’export de celle-ci. Plusieurs types de filtres ont vu le jour : on retrouve d’un côté les filtres de classe et de l’autre des filtres d’attributs. Ces filtres sont définis intégralement grâce aux annotations EXPORTfilter sur des attributs et EXPORToption sur des classes. Les fonctionnements de ces filtres étant différents, nous allons les analyser séparément. • Filtres de classe Les filtres de classe permettent de personnaliser les éléments récupérés sous MySQL, afin d’exporter non pas l’ensemble d’une table mais des résultats filtrés au besoin du front-office. Pour donner un exemple d’utilisation du filtre de classe, je reprendrai mon modèle « Produit » et ajouterai un filtre d’export ciblant les produits actuellement en vente, traduit par un stock d’au moins supérieur à « 1 ». /** * @EXPORTdocument(table="products") * @EXPORToption("stock",">=",1) */ class Product { } L’annotation EXPORToption prendra en paramètre des éléments identiques à ce que prendrait n’importe quel type d’ORM22 ou d’ODM23 : la base de recherche, dans notre cas « stock », puis la condition, ici « supérieure ou égale » et enfin notre variable de comparaison : « 1 ». De ce fait nous n’exporterons que les produits ciblés pour la vente. Côté développement, cette option interagit avec le « Query Builder24 » de Doctrine afin d’ajouter des nouvelles conditions dans notre récupération de produits en stock. 22 « object-relational mapping » 23 « object-document mapping » 24 « Générateur de requête »
  • 33. 32 • Filtres d’attributs Les filtres d’attributs sont utilisés pour formater des données avant de les exporter sous MongoDB. Nous retrouvons ces derniers employés sur des chaines de caractères, des tableaux, des objets… Ces filtres d’attributs sont similaires aux filtres disponibles par certains moteurs de template PHP. La différence notable, comparé à Twig25 ou Smarty26 , provient du fait que ces filtres sont appliqués avant l’enregistrement des données et non pendant leur lecture. Plus encore que de gagner en temps de traitement, ces filtres pré-enregistrement évitent aux intégrateurs des contraintes dans l’affichage de données. Formater les données en amont permet donc de faciliter la lecture en se déchargeant de certaines obligations d’affichage. Les filtres d’attributs utilisés dans notre application restent primaires, mais nous éviterons donc plusieurs manipulations de données lors de leur affichage. On retrouvera des filtres spécifiques aux chaines de caractères : convertir les caractères en minuscule ou majuscule, supprimer les espaces en début et fin de chaînes, retirer d’éventuelles balises HTML27 … Certains filtres sont applicables uniquement aux tableaux : trier un tableau par ordre ascendant ou descendant, ne récupérer qu’une partie d’un tableau… Bien sûr, ces filtres ne seront fonctionnels que sur des tableaux sérialisés28 en base de données. Voici un exemple de filtres annotés au modèle Product où nous souhaitons obtenir le nom du produit en majuscule et la référence nettoyée d’éventuels espaces en début et fin de chaîne. class Product { /** * @EXPORTfilter("uppercase") */ protected $name; /** * @EXPORTfilter("trim") */ protected $reference; } 25 Moteur de template utilisé par défaut sous Symfony 26 Moteur de template utilisé par défaut sous PrestaShop 27 « L’HyperText Markup Language, généralement abrégé HTML, est le format de données conçu pour représenter les pages web ». 28 La sérialisation est un processus visant à coder l'état d'une information qui est en mémoire sous la forme d'une suite d'informations plus petites.
  • 34. 33 3.2.5. Assurer l’intégrité de données sensibles Vérifier l’intégrité des données est une étape relativement similaire à la gestion des filtres d’attributs. Pour les filtres, nous récupérons une donnée puis la formatons selon nos besoins avant de persister notre entité. Nous n’attendons rien en retour des transformations. A l’inverse, les vérifications d’intégrité ont pour but de nous indiquer si les données sont bien valides avant de les persister. Grâce à MongoDB, depuis sa version 3.2, nous disposons d’un validateur intégré et performant. Très facile d’utilisation, il nous permet d’établir des règles de validation à la création d’une collection. Ces contraintes sont traduites des annotations EXPORTintegrity en JSON, à destination des options de création de la collection. Schématisation des étapes de validation sous MongoDB Trois éléments assurant l’intégrité des données ont été mis en place pour notre application : le format, l’unicité et le type. Bien sûr, il est important de rappeler que d’autres éléments pourront venir se greffer à notre soft dans ses prochaines versions. • Vérification d’unicité Cette option nous permet de vérifier qu’un attribut est bien unique dans notre base de données relationnelle avant l’export. Pour assurer cette inspection, notre classe EnsureAttributesUnicity, du système de traitement des données, requête la table correspondante et s’assure que la donnée est bien unique. Les méta-données à ajouter sont : /** * @EXPORTintegrity(unique=true) */ protected $email;
  • 35. 34 • Vérification de format Grâce au paramètre « format » de notre annotation, nous pouvons nous assurer que la donnée est bien valide à nos yeux et peut donc être persistée sans problème. La valeur du format est renseignée avec l’aide des expressions régulières29 . Pour traiter ces informations et assurer l’intégrité du format, j’utilise une fonction native PHP 4 : preg_match. /** * @EXPORTintegrity(format="/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0- 9]|3[0-1])-[0-9]+$/") */ protected $reference; • Vérification de type Pour finir ce chapitre sur l’intégrité des données, voici la dernière option mise en place sur notre application : la vérification du type. Bien sûr, quand on parle de type, il s’agit bien du type d’un attribut. Un test est effectué afin de vérifier si le type de donnée récupérée est valide pour le validateur MongoDB. Côté PHP, nous avons également une fonction native PHP 4 : gettype pour s’assurer de la bonne récupération de cette information. En annotation on indiquera : /** * @EXPORTintegrity(type="double/") */ protected $price; 29 « Expression régulière ou REGEX est une chaîne de caractères, qui décrit, selon une syntaxe précise, un ensemble de chaînes de caractères possibles. »
  • 36. 35 3.3. Mise à jour des données La mise à jour des données s’effectue simplement grâce à l’ajout du champ « mongo_id » dans les tables à exporter. Pour rappel, notre configuration prend en charge les mises à jour, mais s’assure aussi de la présence de cette nouvelle colonne grâce au fichier manifesto.yaml. export: update_on: "mongo_id" L’initialisation de « mongo_id » intervient lors de la persistance d’un document. Si, et seulement si, le document est jugé valide par MongoDB et est persisté en base de données, un nouveau processus de mises à jour est lancé. La classe EnsureUpdateData est alors instanciée et est pleinement connectée avec ConnectImport afin d’assurer l’ajout de l’identifiant unique du document dans notre champ « mongo_id ». Cette étape est la dernière à être réalisée dans l’export des données. Schématisation de l’intervention du processus de mises à jour Afin de nous assurer une redondance continue et fonctionnelle, nous détaillerons les différents process de mises à jour. Chaque point se veut simple et dédié à une fonctionnalité unique. • Premier export Cette étape est celle que nous avons analyser tout au long de ce mémoire : les données sont récupérées, traitées, validées et persistées. Ce n’est qu’après toutes ces étapes que notre classe
  • 37. 36 EnsureUpdateData récupère l’ « id 30 » d’insertion du document et le met à jour dans le champ « mongo_id ». Nous pouvons maintenant assurer la partie mise à jour et suppression des données. • Mise à jour Si, lors du processus d’export, la ligne référencée possède un « ObjectId » ou identifiant MongoDB, nous basculerons sur un nouveau processus. En effet, en sortie de traitement, les données à importer (en tant que document) interagissent avec la classe DataExport de manière à être transformées en JSON, puis persistées. Puisque nous savons qu’il ne s’agit pas, ici, d’un premier export, nous chargerons plutôt EnsureDataUpdateExport qui a pour vocation de mettre à jour le document référencé au lieu d’en ajouter un nouveau. • Suppression Pour finir, un service CleanIndexAutomat a été déployé. Il implémente nos classes DataExport pour le premier export et EnsureDataUpdateExport pour une mise à jour. A chaque appel de ces classes, une analyse comparative intervient dans le but de supprimer d’éventuels documents n’étant plus référencés sous MySQL. A la fin de ce traitement, nous avons récupéré une liste de documents solitaires. Une simple requête nous permet de les retirer de la collection concernée. Schématisation globale de la mise à jour 30 « id » pour identifiant
  • 38. 37 CONCLUSION A travers ce mémoire nous avons exploré, étape par étape, le processus de développement d’une application sur mesure basée sur une problématique liée à mon travail de tous les jours. La redondance de données est un sujet complexe qui a modifié toute ma façon de penser ce sujet : l’analyse des besoins et des solutions existantes a été le pivot central dans la réalisation de ce projet. Nous possédons maintenant une application fonctionnelle qui répond à toutes nos attentes dans l’import/export continu, ou, dans la redondance des données. Une étape de réflexions supplémentaires m’a permis d’analyser la solution que j’ai fournie à la fin du développement : nous noterons que l’application livrée pourra être améliorée, ou, optimisée de diverses façons. Pour commencer, j’aimerais parler du processus global d’export de MySQL vers MongoDB. Je suis réellement satisfait de sa conception et de son développement. Toutefois, certains process sont à revoir, dans l’objectif principal d’améliorer les performances d’exports à grande échelle. Ensuite, le soft étant censé faciliter la vie du développeur, il serait utile de pouvoir ajouter, au système de traitement des données, des filtres et des processus de vérification d’intégrité personnalisés. En effet, nous pourrions aisément importer de nouvelles options au fichier de configuration afin de prendre en compte des méthodes sur mesure, adaptées à la logique de l’entreprise. Pour finir, il serait intéressant de développer cette application à des bases de données autres que MongoDB et MySQL. Même s’ils sont leaders dans leur domaine, d’autres outils existent et sont aussi populaires : nous retrouvons MariaDB et PostreSQL pour les bases de données relationnelles, et CouchDB et Riak pour les bases orientées document.
  • 39. 38 ANNEXES Annexe 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Tableau comparatif 31 entre MySQL et MongoDB : - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 31 Source: HACKERNOON https://hackernoon.com/mongodb-vs-mysql-comparison-which-database-is-better- e714b699c38b
  • 40. 39 Annexe 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Relation du deuxième degré, un schéma d’export invalide : Intégration d’un document dans un document intégré au document source. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /** * @EXPORTdocument(table="products") */ class Product { /** * @EXPORTeject(document="Fabricant", related="id_fab") */ protected $fabricant; } /** * @EXPORTdocument(table="fabricants") */ class Fabricant { /** * @EXPORTeject(document="MaisonMere", related="id_house") */ protected $maisonMere; } /** * * @EXPORTdocument(table="maisons") */ class MaisonMere { /** * @EXPORT * */ protected $name; }
  • 41. 40 Annexe 3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Relation du premier degré, un schéma d’export valide : Injection de données dans un document intégré au document source. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /** * @EXPORTdocument(table="products") */ class Product { /** * @EXPORTeject(document="Fabricant", related="id_fab") */ protected $fabricant; } /** * @EXPORTdocument(table="fabricants") */ class Fabricant { /** * @EXPORTinject(document="MaisonMere", related="id_house" {"name"}) */ protected $maisonMere; } /** * * @EXPORTdocument(table="maisons") */ class MaisonMere { /** * @EXPORT * */ protected $name; }
  • 42. 41 Annexe 4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Configuration de docker : docker-compose.yaml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - version: '2' services: ### PHP-CLI Container ####################################### php-cli: image: php:cli ### MySQL Container ######################################### mysql: build: ./${DOCKER_DIRECTORY}/mysql ports: - "${MYSQL_PORT}:3306" environment: MYSQL_DATABASE: ${MYSQL_DATABASE} MYSQL_USER: ${MYSQL_USER} MYSQL_PASSWORD: ${MYSQL_PASSWORD} MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} ### MongoDB Container ####################################### mongo: build: context: ./${DOCKER_DIRECTORY}/mongo dockerfile: ${MONGODB_DOCKERFILE} ports: - "${MONGODB_PORT}:27017"