Académique Documents
Professionnel Documents
Culture Documents
Dans MongoDB, les documents sont stockés sous format BSON (Binary JSON) et ma-
nipulés en format JSON. Il est donc nécessaire de se familiariser avec ce format. Com-
mençons par quelques exercices dans cette direction.
Le JSON (JavaScript Object Notation) sert, comme son nom l'indique, à représenter
des objets en JavaScript. Dans un langage de programmation, un objet est composé
de champs de données (des variables de diérents types) et de méthodes. Le JSON ne
sert qu'à représenter les données. D'une certaine manière, il s'agit simplement d'une
structure de données imbriquées.
Pour être plus précis, JSON est un format d'échange d'objets sous forme de texte (pour
contourner les soucis de compatibilité) d'une application à l'autre. Ces applications
peuvent être écrites en diérents langages et fonctionner très diéremment ; elles sauront
toujours comprendre une chaîne de caractères. Ce principe de transformer un objet en
texte pour pouvoir l'échanger facilement s'appelle sérialisation (serilize ou stringify selon
les langages).
Voici un exemple d'objet écrit en JSON :
{
" title " : " Titanic " ,
" year " : 1997 ,
" genre " : " drama " ,
" actors " : [
{
" first_name " : " Kate " ,
" last_name " : " Winslet " ,
" birth_date " : 1975 ,
" role " : " Rose DeWitt Bukater "
},
{
" first_name " : " Leonardo " ,
" last_name " : " DiCaprio " ,
" birth_date " : 1974 ,
" role " : " Jack Dawson "
}
]
}
Remarquons que dans l'exemple de JSON proposé, l'indentation a été travaillée pour
rendre l'objet plus lisible. Lorsque du JSON est présenté à un humain, on essaie de
toujours respecter ce standard. Lorsque l'objet est seulement envoyé d'une application
à une autre, les retours à la ligne et diérents espaces sont supprimés pour gagner de la
place. Il est donc tout à fait correct d'écrire l'objet précédent sous la forme :
{ " title " : " Titanic " ," year ":1997 ," genre ":" drama " ," actors ":[{" first_name
":" Kate " ," last_name ":" Winslet " ," birth_date ":1975 ," role ":" Rose
DeWitt Bukater "} ,{" first_name ":" Leonardo " ," last_name ":" DiCaprio " ,"
birth_date "1974 ," role ":" Jack Dawson "}]}
MongoDB est une base de données orientée documents. Elle peut travailler de manière
répartie sur plusieurs noeuds. Dans ce cas, les données sont shardées sur ces noeuds.
Cela signies qu'elle sont réparties et dupliquées pour assurer la disponibilité même
en cas de défaillance d'un noeud. Le sharding peut être géré de manière automatique
par MongoDB mais peut également être paramétré par le développeur. Cela dépend
fortement des besoins et de la topologie du réseau. Nous laisseront cet aspect de côté
dans nos TP.
Par ailleurs, MongoDB est recommandé dans le cas de stockage de données très volumi-
neuses (plusieurs Go). Dans le cadre de nos TP, notre espace de stockage est limité et
nous travaillerons sur des jeux de données très réduits.
L'objectif de ces TP est de manipuler les opérations de base de manipulation et d'in-
terrogation des données sous mongoDB. On s'attachera à faire apparaître les diérences
par rapport à un SGBDR classique.
Dans la vraie vie, le serveur mongoDB sera sur une ou plusieurs machines dédiée à
l'hébergement. Le requêtes parviennent de l'extérieur et sont émises par des applications
ayant besoin d'accéder aux données. Lors de notre TP, nous allons tout faire en local,
sur une seule machine. Cela ne change rien à la forme que doivent prendre les requêtes.
2. Lancer le serveur mongoDB. Pour cela, il faut se rendre dans le répertoire C :\Program
Files (x86)\MongoDB\Server\NumVersion\bin et exécuter mongod.exe.
Garder le terminal ouvert et ne plus y toucher. C'est le serveur mongoDB qui
tourne et attend des connexions.
3. Ouvrir un nouveau terminal qui nous servira à communiquer avec le serveur. Pour
cela, dans le même répertoire que précédemment, lancer mongo.exe. Une invite de
commande de la forme > vous donne alors la main.
A partir de là, nous allons écrire des commandes que nous passerons au serveur Mon-
goDB. N'hésitez pas à copier/coller ces commandes depuis Notepad++. L'édition y est
plus conviviale et cela vous permettra de garder une trace du TP.
4. Tester les commandes suivantes dans le terminal.
(a) Voir les bases de données disponibles :
show dbs
(c) Plaçons nous dans la base TP_test. Pour se placer dans une base de données :
use < nomBaseDeDonnees >
(e) On obtient la liste des collections dans la base de donnée active par :
show collections
5. Lancer Robo3T (s'il est installé sur la machine). Se connecter au serveur Mon-
goDB local. Robo3T dispose d'une interface plus conviviale pour dialoguer avec le
serveur. A l'aide d'un clic droit sur le serveur local (panneau de gauche), choisir
New Shell . Une fois dans un onglet de type Shell, vous pouvez en ouvrir de
nouveau à l'aide de Ctrl+T.
(a) Lancer de nouveau les première commandes de la questions précédente an
de créer une base de données, une collection et 3 documents. Remarque : il
faut ouvrir un shell après un clic droit sur la bonne base de données pour
pouvoir entrer les commandes.
(b) Eectuer un nd pour consulter ces documents. Remarquer en haut à droite
de la fenêtre de résultat les trois options possibles pour l'achage : tree, table
ou text. Dans le cadre de ce TP, on préférera text. Dans le menu option,
default view mode, choisir text.
(c) Toutes les commandes que vous envoyez à MongoDB sont en javascript.
Robo3T vous ore la possibilité de sauvegarder vos commandes dans des
chiers js (pratique pour réviser...). N'hésitez pas à sauvegarder vos com-
mandes les plus complexes de cette manière. Vous pouvez également enregis-
trer des programmes de plusieurs lignes. A l'exécution, Robo3T vous ouvrira
une fenêtre par commande ayant une valeur de retour.
Nous allons travailler avec une (petite) base de données de lms. Un lm contiendra les
informations suivantes : id, titre, année, genre, résumé, pays, réalisateur, acteurs (et le
rôle associé dans le lm).
Les acteurs et les réalisateurs sont des artistes, qualiés par leur id, nom, prénom et
année de naissance.
Nous allons créer cette base de donnée, mais dans mongoDB. On est donc dans un
contexte NoSQL, ou plus précisément non relationnel. On peut donc s'attendre à trou-
ver un nombre de collections ne correspondant pas au nombre de tables du modèle
relationnel. A votre avis, combien de collections va-t-on utiliser ?
6. Créer une nouvelle base de données MoviesTP et se placer dedans.
7. Nous allons importer une collection déjà prête. Elle se trouve dans le chier mo-
vies.json.
(a) Ouvrir ce chier avec notepad++ pour voir comment il se présente.
(b) Importer ce chier en tant que collection. Pour cela, nous allons utiliser l'uti-
litaire d'importation prévu par MongoDB. Ouvrir un terminal avec cmd.exe
(dans windows, sys32). Se rendre dans le répertoire où se trouve votre chier
json (avec la commande cd). Une fois dans le répertoire, il faut appeler l'utili-
taire avec son chemin complet (compléter avec tab) et faire suivre des options
-d NomBDD -c NomCollection le chierAImporter.json jsonArray. Cela
donne quelque chose comme :
" c :\ Program Files \ MongoDB \ Server \3.4\ bin \ mongoimport . exe "
-d MoviesTP -c movies -- file movies . json -- jsonArray
(c) Remarquer que ce chier donne lieu à une seule collection qui contient toutes
les informations. Il y a donc des redondances dans les informations des ar-
tistes, mais d'un autre côté, si l'on récupère un lm, on a toutes les infor-
mations nécessaire sans fournir d'eort supplémentaire. Bienvenue dans le
monde du NoSQL !
8. Questions à se poser pour prendre du recul sur les bases de données orientées
documents :
(a) Pourquoi peut-on dire que les documents structurés sont auto-décrits ?
Quel sont les avantages et les inconvénients ?
(b) Quel est l'intérêt (dans le cadre d'un système NoSQL à grande échelle) des
structures riches et imbriquées qui permettent de construire des documents
complexes ?
(c) La modélisation entité-association reste-elle utile pour des bases NoSQL ?
Et le modèle relationnel ? Comment pourrait-on déduire la structure de nos
documents à partir du schéma entité-association ?
(d) Pourrait-on envisager de créer autant de collections qu'il existe de points
d'entrée vers les données ? Par exemple, notre base Films comprendrait des
documents centrés sur les lms (Alien et tous ses artistes) dans une collection,
et d'autres centrés sur les réalisateurs (Tarantino et tous les lms qu'il a
tournés) dans une autre collection. D'après vous, quels seraient les avantages
et les inconvénients ?
Nous avons rencontré la méthode nd qui sert à renvoyer tous les documents d'une
collection. Heureusement, il y a moyen de faire des choses bien plus précises lors de
l'interrogation des données. Cela nécessite toutefois de connaître la structure des docu-
ments.
9. Sortir la liste des lms de 1992. Il faut pour cela ajouter un ltre dans la méthode
nd.
db . getCollection ( " movies " ) . find ({ " year " : 1992})
Remarquons que ce ltre prend la même forme que dans la méthode update utilisé
précédemment.
Remarquons également qu'une syntaxe alternative a été utilisée pour faire réfé-
rence à la collection movies : getCollection("nomCollection"). En réalité, c'est tou-
jours cette méthode qui est utilisée mais lorsque nomCollection est une chaîne de
caractère sans espaces ni caractères spéciaux (ni mots-clés), taper db.nomColletion
est traduit par le serveur en getCollection("nomCollection"). De manière générale,
en tapant les commandes à la main dans un terminal, on préférera db.nomCollection
qui est plus simple, mais dans le code d'une application, on utilisera toujours ex-
plicitement getCollection().
Pour rendre ce résultat plus présentable (si vous travaillez dans un terminal),
vous pouvez ajouter .pretty() à la n de la commande pour mettre en forme
automatiquement le JSON.
db . getCollection ( " movies " ) . find ({ " year " : 1992}) . pretty ()
10. Se rendre sur le site ociel de la documentation MongoDB qui est, soit dit en
passant, de très bonne qualité. Inutile de chercher la version française. En infor-
matique, les documentations anglaises sont généralement recommandées, même si
la version française existe, car elles sont plus proches de la syntaxe du langage.
Chercher la documentation sur la méthode nd(). Vous la trouverez dans Reference
> mongo Shell Methods > Collection Methods > db.collection.nd().
Prenez le temps de lire les premiers paragraphes, regardez en diagonale ce que l'on
trouve et jetez un ÷il aux exemples.
De même, sachez que la documentation de db.collection.distinct() pourra vous être
utile pour répondre aux questions suivantes.
Trouvez les informations nécessaires an d'écrire les requêtes suivantes :
(a) Lister tous les weterns
(b) Lister les lms sortis depuis 1992.
(c) Lister (en une seule requête) les westerns et les drames.
(d) Lister les westerns sortis au plus tard en 1992.
(e) Lister tous les titres de lm (uniquement les titres).
(f) Lister tous les genres (sans doublons).
(g) Lister les lms où Leonardo DiCaprio a joué.
(h) Lister les noms des acteurs ayant joué avec Leonardo DiCaprio.
La technique la plus courante (et recommandée) avec mongoDB pour eectuer des agré-
gations de données est la méthode aggregate(). Elle repose sur la notion de pipeline
et de stage . Le mot stage se traduit facilement en français par étage ou étape.
Malheureusement, le mot pipeline (provenant initialement de la micro architecture des
processeur) n'a aucune traduction convenable. On pourrait le remplacer par chaîne de
traitement de données mais ce serait un peu long. On peut également le traduire par
tube mais cela ne donne pas d'idée précise de ce qu'il représente.
Prenons la métaphore du tube. Lorsque l'on fait une agrégation avec un pipeline, disons
par exemple une somme pour des éléments respectant une contrainte, les documents
de la collection sont tous envoyés dans le pipeline (tube). Ce pipeline est composé de
deux stages (étapes). Tous les documents doivent traverser les stages dans l'ordre avant
de ressortir de l'autre côté du pipeline sous forme agrégée. Dans notre exemple, on
commencerait par ltrer (stage 1), puis on sommerait (stage 2).
11. Regarder, dans la documentation MongoDB, le chapitre Aggregation Pipeline dans
Aggregation (directement dans les racines à gauche).
Pour avoir idée des stages possibles, regarder Reference > Operators > Aggrega-
tion Pipeline Operators > Pipeline Aggregation Stages. Il faudra entrer dans les
détails des stages les plus classiques pour répondre aux questions suivantes.
(a) Acher par ordre chronologique les lms de Christopher Nolan.
(b) Reprendre la question précédente en projetant sur titre et année du lm.
(c) Compter le nombre de fois où Morgan Freeman et Clint Eastwood ont joué
ensemble.
(d) Compter le nombre de lms par réalisateur et trier par ordre décroissant (de
nombre de lms).
(e) Même question, mais par acteur (attention, c'est plus compliqué).
(f) Pour chaque genre de lm, faire la moyenne des années de sortie.
(g) Quel est le duo réalisateur / acteur ayant travaillé ensemble le plus grand
nombre de fois ?
(h) Lister tous les acteurs (non, prénom, naissance).
(i) Lister tous les acteurs avec la liste des rôles qu'ils ont tenu (et le titre du lm
associé).
III.D MapReduce
Pour se familiariser avec MapReduce, commençons pas des choses simples (qu'il est
préférable de faire avec les pipelines d'agrégation, mais nous sommes ici pour apprendre).
12. Ecrire les fonctions map et reduce puis lancer l'instruction mapReduce pour ré-
pondre aux questions suivantes :
(a) Pour chaque lm, compter le nombre d'acteurs répertoriés dans la base de
données.
(b) Pour chaque acteur, compter le nombre de lms.
III.E Index
Comme dans la plupart des systèmes de bases de données (relationnels ou non), Mon-
goDB propose une gestion d'index. Sans index, lorsque l'on exécute une requête sur une
collection, MongoDB doit regarder tous les documents de la collection pour voir ceux
qui répondent aux critères. Cela est coûteux.
Il est judicieux de construire un index sur un champ qui est souvent utilisé comme critère
dans les requêtes. MongoDB mémorise alors les valeurs de ce champs dans l'ordre et
entretien ce tri au fur et à mesure de l'évolution des données. Il y a donc un léger coût
lors de la manipulation des données, mais les interrogations de données sont bien plus
performantes.
13. Regarder (rapidement) la documentation de MongoDB sur les index puis répondre
aux questions suivantes.
(a) Reprendre quelques unes des requêtes nd() précédentes et regarder le plan
d'exécution à l'aide de .explain() ajouté à la n de la requête.
(b) Créer un index sur un des champs utilisé dans les requêtes (par exemple
genre).
14. Regarder de nouveau les plans d'exécution.
Vous ne serez pas en mesure de voir une diérence de vitesse en local sur un si
petit jeu de données mais elle serait énorme sur une application réelle dans un
contexte Big Data.
IV Jointures et MongoDB
Dans cette section, posons-nous la question des jointures en MongoDB. Est-il possible,
comme dans le monde relationnel, de "pointer" vers un autre document ?
On se propose de travailler de nouveau avec la base de données des lms mais celle-ci a
été remaniée pour approcher le concept de la jointure.
Si l'on veut l'ensemble des acteurs (nom et prénom) ayant joué dans un lm, on com-
mence par récupérer l'ensemble des lms que l'on stocke dans une variable. On simule
ensuite la jointure et allant chercher tous les artistes désignés par leur clé dans le do-
cument récupéré. Il y a donc plusieurs instructions à écrire en javascript. Si vous ne
connaissez pas ce langage, regarder rapidement sur internet les éléments de base de
la syntaxe (déclaration, aectation, if, boucles). Notez qu'il s'agit d'un langage orienté
objet.
var film = db . movies . findOne ({ " title " : " Sleepy Hollow "}) ;
for ( var i =0; i < film . actors . length ; i ++)
{
var actor = db . artists . findOne ({ " _id " : film . actors [ i ]. _id }) ;
film . actors [ i ]. last_name = actor . last_name ;
film . actors [ i ]. first_name = actor . first_name ;
}
print ( film ) ;
Notez bien qu'il n'y a pas réellement eu de jointure. Le serveur n'a pas fourni le travail
permettant de former un agrégat. C'est le client qui s'en charge et qui envoie un (très)
grand nombre de requêtes pour récupérer toutes les informations souhaitées.
18. Nous allons maintenant eectuer des requêtes déjà eectuées précédemment. Pen-
sez à comparer les deux approches, tant sur le plan de l'élégance que sur celui
de la performance.
(a) Lister tous les weterns
(b) Lister les lms où Leonardo DiCaprio a joué.
(c) Lister les noms des acteurs ayant joué avec Leonardo DiCaprio.
(d) Compter le nombre de lms par réalisateur et trier par ordre décroissant (de
nombre de lms).
(e) Même question, mais par acteur.
(f) Quel est le duo réalisateur / acteur ayant travaillé ensemble le plus grand
nombre de fois (on veut leurs noms et prénoms) ?
(g) Lister tous les acteurs (non, prénom, naissance).
(h) Lister tous les acteurs avec la liste des rôles qu'ils ont tenu (et le titre du lm
associé).
V Requêtes géospatiales
MongoDB ore la possibilité d'indexer les objets d'une collection par des coordonnées
géospatiales. Cela permet, par exemple, de répondre à des requêtes du type : Quelle
est la pizzeria la plus proche de moi ? .
19. Importer dans une nouvelles base de données la collection des villes qui est dis-
ponible dans le chier cities.json sur Umtice. Il contient de nombreuses villes du
monde (essentiellement de plus de 1000 habitants).
20. Cherchez dans la documentation mongoDB comment répondre aux questions qui
suivent.
(a) Créez un index 2dsphere à l'aide du champ coordinates.
(b) Récupérer les coordonnées des villes de Paris, Chambéry, Lyon et Strasbourg
(c) Recherchez les villes à moins de 10km de Paris.
(d) Faites le total de population dans ce disque.
(e) Déterminez les villes non françaises présentes dans le triangle Lyon - Cham-
béry - Strasbourg.
(f) Combien y en a-t-il ?
21. Sur la base de données de villes, on pourra, à titre d'exercice, chercher à répondre
aux questions suivantes :
(a) Supprimer de la base de données toutes les villes n'ayant pas 1000 habitants
ou plus.
(b) Eectuer un classement des pays par nombre moyen d'habitants par ville.
Croissant, puis décroissant.
(c) Dans ce classement, éliminer les pays comptant moins de 100 villes.
(d) Combien y a-t-il d'habitant par ville en France ?
(e) Combien trouve-t-on d'habitant en France dans ces données ? Combien de
personnes vivent donc dans des villes/villages de moins de 1000 habitants ?
(ces données datent de 2017, en moyenne)
(f) Quelles sont les villes à la même longitude que Paris (±1°) ? Les classer du
nord au sud.
(g) Quelle est la bande de longitude (largeur 1°) la moins peuplée ? La plus peu-
plée ?