Vous êtes sur la page 1sur 19

Bases de données NoSQL

TP MongoDB
Configuration de la VM nosql2022 (si vous l’utilisez) :
- OS : Ubuntu 64 bits
- 2 cœurs de processeurs (ou plus).
- RAM : 4 Go (ou plus)
- Augmenter la taille de la mémoire vidéo au maximum + activer l’accélération 3D
- Login (root) : nosql ; mot de passe : nosql
- Activer le presse-papier partagé (bidirectionnel)
- Si l’affichage de la VM est en faible résolution, installer les Additions Invité (drivers) : Menu
Périphériques puis Insérer l’image CD des Additions Invité… L’image d’un CD va alors être chargée
et les drivers installés. Redémarrer si nécessaire la machine virtuelle et changer la résolution de
l’affichage.

La VM contient MongoDB en version 5.0.x.

TP noté à rendre en binôme.


Conservez TOUT de votre code (y compris les INSERT).

1. Configuration et lancement

Démarrage du serveur
Lancer un Terminal et démarrer le serveur MongoDB :
cd mongodb/bin
./mongod --dbpath /home/nosql/mongodb/data/db

Remarques :
• Le dossier contenant les BD NoSQL est : /data/db. Il est nécessaire de le créer au préalable.
Il est possible, comme nous l’avons fait, de définir un chemin de localisation des données en
utilisant l’option --dbpath de l’exécutable mongod.
• Si les fichiers de MongoDB ne sont pas considérés comme des exécutables, dans le home de
l’utilisateur nosql, exécuter la commande suivante :
chmod -R 777 mongodb

Mot de passe root : nosql

Cette commande démarre le processus principal de la base de données. Vous devez obtenir l’écran
suivant (attente de connexions) :

Comme on peut le voir, le daemon mongod fonctionne par défaut sur l’hôte localhost et le port 27017.
Ne pas fermer cette fenêtre.

Connexion à MongoDB
Le shell mongo.sh (situé dans mongodb/bin) permet de se connecter au daemon mongod. Exécuter le shell
dans une nouvelle fenêtre Terminal (./mongo).

Vincent COUTURIER 1
Vous devez obtenir le prompt > permettant de saisir les commandes MongoDB.

Remarques :
• La commande mongo sert à manipuler MongoDB. C’est un shell s’appuyant sur un moteur javascript, et
va donc permettre d’utiliser toutes les fonctions standard du javascript en plus des commandes de
base de données qui n’utilisent pas la syntaxe javascript (use, show, etc.).
• Pour se connecter à une base distante et/ou un port différent, on ajoutera les paramètres –port et –
host à la suite de la commande mongo

A la place du shell, il est possible d’utiliser Robo3T (anciennement robomongo). Lancer robo3t à partir de
la logithèque Ubuntu :

L’exécutable se trouve également dans Ordinateur > snap > robo3t-snap > 4 > bin.

Connexion (cliquer sur le lien « Create ») :

Vincent COUTURIER 2
La connexion au server local est configurée par défaut. Cliquer sur « Test », puis sur « Save ».

Cliquer sur « Connect ».

Remarque : vous pouvez aussi utiliser MongoDB Compass, le client « officiel », installé dans la VM, mais
privilégiez la console plutôt que le query builder car il vous sera demandé l’écriture de requêtes en DS.
Query builder pour la recherche de documents :

Vincent COUTURIER 3
Query builder pour insérer un document (NE PAS L’UTILISER) :

Console :

Vincent COUTURIER 4
2. Utilisation de MongoDB

Modèle de données de MongoDB :


• Database (= Base de données)
• Collection (= Table)
• Document (= ligne d’une table) = document BSON dont le contenu est constitué de couples
clés/valeurs. Les valeurs pouvant être des entiers, réels, chaines de caractères, des objets (dates,
binaires, liens vers un document, etc.), tableaux ou un autre document, c’est à dire, pouvant à son
tour contenir un autre ensemble de clés/valeurs qui peuvent aussi contenir des documents et ainsi
de suite... Dans un document, des champs peuvent être ajoutés, supprimés, modifiés et
renommés à tout moment.
• Field (= Colonne). Les champs d’un document sont libres et peuvent être différents d’un
enregistrement à un autre au sein d’une même collection (ATTENTION cependant à ne pas faire
n’importe quoi !).
• _id (= Clé primaire). Seul champ commun et obligatoire. Si vous ne l’écrivez pas (vous même)
dans le fichier JSON, il sera automatiquement créé.

Options sur la connexion : créer une nouvelle base de données ; version du SGBD, etc.

Remarque : dans le shell, on peut exécuter les commandes suivantes (inutiles dans le client graphique) :
• db : pour connaître la base courante
• db.version() : pour connaître la version du serveur MongoDB. Dans l’outil graphique :

Vincent COUTURIER 5
• show dbs : pour connaitre les bases gérées pas le server mongod sur lequel on est connecté
(seules les bases non vides, i.e. contenant des collections sont affichées).
• use NomDeLaBase : pour choisir une base. Si la base de données n’existe pas, celle-ci sera créée
au moment de l’insertion de données ou à la création manuelle d’une collection vide de documents
dans celle-ci.

Créer la base bdetudiants.

Ouvrir le shell qui vous permettra par la suite d’exécuter les commandes.

Nous allons manipuler des documents BSON. BSON permet de gérer des types de données divers : byte,
int32, int64, double, ObjectID, Timestamp, Date, tableaux, etc. (http://bsonspec.org).

Méthodes (principales) CRUD :


• insertOne() et insertMany()
• find() et findOne()
• update()
• remove()
Autres méthodes : https://docs.mongodb.com/manual/reference/method/

2.1. Insertion de données

Quand on insère des données (sous forme de document) dans une collection inexistante, MongoDB crée la
collection implicitement. De même si la base de données n’existe pas.
Dans la base de données bdetudiants (use bdetudiants), ajouter les documents suivants à la collection.

var etudiant = { // Création d’un objet JSON


"_id" : 1, // On peut aussi utiliser ObjectId('50d7423224e20473b53cae72')
"nom" : "DURAND",
"prenoms" : ['Alain', 'Paul'],
"adresse" : {
"numero" : "12",
"rue" : "Rue Arc en Ciel",
"ville" : "Annecy",
"cp" : "74000"
},
"date naissance" : ISODate("1977-08-01T15:00:00Z")
}
// on ajoute le document etudiant dans la collection etudiants
db.etudiants.insertOne(etudiant)

« F5 » pour exécuter ou bouton :

Vincent COUTURIER 6
db.etudiants.findOne() // Retourne un seul étudiant. Sensible à la casse !

Dans Robo3T :

Tester les 3 boutons situés à droite.

Dans le shell Mongo (Terminal) :

Vincent COUTURIER 7
Remarques :
• Vous pouvez utiliser l’aide de façon suivante pour afficher les informations sur les commandes :
help, db.help(),db.<collection>.help(), db.<collection>.find().help(), etc.

• En saisissant les commandes sans parenthèses, vous pouvez également voir le code des
commandes :

Vous pouvez maintenant vérifier que la collection a bien été créée :

Vous devrez utiliser la commande show collections dans le shell Linux.

Remarque : le fichier JSON précédent montre comment on peut modéliser une application simplement. On
s’affranchit d’utiliser une collection pour les adresses par exemple. On parle de dématérialisation ou
d’imbrication de documents (le champ adresse contient un document de 4 champs). Ici, elle a un sens car
Vincent COUTURIER 8
les données (adresses) sont distinctes et elle permet d’accéder rapidement aux données. Elle n’en a pas
toujours quand on retrouve fréquemment les mêmes données (par exemple, même informations sur le
diplôme, etc.). Se pose alors la question de la redondance et surtout de la modification (écritures
multiples nécessaires).

Créer un 2ème étudiant.


Remarque pour insérer en masse : insertMany :
https://docs.mongodb.com/manual/reference/method/db.collection.insertMany/

var etudiant = {
"_id" : 2,
"nom" : "DURAND",
"prenoms" : ['Marc'],
"date naissance" : ISODate("1985-06-10T00:00:00Z"),
"adresse" : {
"numero" : "12",
"rue" : "17 Avenue de la Concorde",
"ville" : "Dijon",
"cp" : "21000" }
}
db.etudiants.insertOne(etudiant)

db.etudiants.find()
// identique à db["etudiants"].find() ou db.getCollection("etudiants").find() ou
db.etudiants.find({})

Créer un 3ème étudiant.


db.etudiants.insertOne({
"_id" : 3,
"nom" : "MARUIL",
"prenoms" : ['Antoine','Alain']
})

Créer un 4ème étudiant (sans la colonne _id). Vérifier que la colonne _id a bien été ajoutée (un ObjectId
a été généré).
db.etudiants.insertOne({
"nom" : "EVENOT",
"prenoms" : ['Vincent','Paul'],
"adresse" : {
"numero" : "12",
Vincent COUTURIER 9
"rue" : "Arc en Ciel",
"ville" : "Annecy",
"cp" : "74000"
},
"notes" : [3.0,5.0,8.0,18.0,19.0],
"annee experience" : 3
})

Ajouter d’autres étudiants (au minimum 3 de plus). Vous pourrez utiliser http://generatedata.com
pour compléter votre jeu de données.

2.2. Requêtes

Rechercher un/des étudiants :


db.etudiants.find({'_id':2})
db.etudiants.find({'nom':'DURAND'})
db.etudiants.find({'nom':'DURAND'}).pretty()
db.etudiants.find({'nom':'ABC'})

Essayer également les requêtes précédentes dans le shell MongoDB (Terminal) pour voir les
différences d’affichage. Il sera nécessaire de charger la base des étudiants : use bdetudiants.

Opérateurs logiques : https://docs.mongodb.com/manual/reference/operator/query-logical/


Opérateurs de comparaison : https://docs.mongodb.com/manual/reference/operator/query-comparison/
Opérateurs d’agrégat : https://docs.mongodb.com/manual/reference/operator/aggregation-pipeline/
Autres opérateurs : https://docs.mongodb.com/manual/reference/operator/query/

Ecrire des requêtes permettant de montrer l’utilisation des opérateurs précédents. Vous devrez
ajouter des données.
Exemples de requêtes :
A. find()
1. Afficher le nom des étudiants habitant à …
2. Afficher les étudiants habitant à … (sans l’ID)
3. Afficher les étudiants habitant à … ou à …
4. Afficher les étudiants habitant à … ou à … ordonné par … décroissant
5. Afficher les étudiants dont le … est parmi … (utiliser $in)
6. Afficher les étudiants dont le … est … et le … est …
7. Afficher tous les étudiants n’habitant pas à …
8. Afficher les étudiants n’habitant ni à …, ni à …
9. Afficher les étudiants dont l'un des prénoms n'est ni … ni …
10. Afficher les étudiants qui habitent à … mais pas dans la rue …
11. Afficher les étudiants ayant plus de … ans d’expérience
12. Afficher les étudiants dont … est présent
13. Afficher les étudiants dont l’un des prénoms commence par …

B. aggregate(), count(), distinct() etc.

Vincent COUTURIER 10
14. Afficher les étudiants à partir du numéro 2 (utiliser skip ou $skip)
15. Trier les étudiants par … décroissant
16. Afficher le nombre moyen d’années d’expérience des étudiants
17. Afficher le nombre moyen d’années d’expérience par … (par ex. par ville).
18. Afficher le nombre moyen d’années d’expérience par … et par … (par ex. par ville et par CP).
19. Afficher le nombre d’étudiants habitant à …
20. Afficher le nombre d’étudiants dont le champ … est présent
21. Afficher le nombre d’étudiants ayant un nom différent
22. Afficher par ordre décroissant, pour chaque prénom existant, le nombre d'étudiants qui portent
ce prénom (vous pourrez utiliser $unwind)
Etc.

2.3. Modification, suppression

Commande updateOne (https://docs.mongodb.com/manual/tutorial/update-documents/)


db.etudiants.updateOne({'_id':2}, {$set : {"nom" : "DURAND2"}})
OU MIEUX, traitement en masse avec updateMany :
https://docs.mongodb.com/manual/reference/method/db.collection.updateMany/

Commande remove (https://docs.mongodb.com/manual/reference/method/db.collection.remove/) :


db.etudiants.remove({'_id':2})

Tester ces commandes :

2.4. Modélisation des collections, jointures

Dupliquer la collection etudiants en etudiants2 :

Remarque : Pour dupliquer une collection dans Compass, créer d’abord la 2nde collection, puis :
db.collection1.aggregate([{ $match: {} }, { $out: "collection2" }])

Vincent COUTURIER 11
Créer la collection formations (dans la même base de données).

Ajouter les formations suivantes dans la collection formations :


_Id Sigle Intitule Annee_creation Institution
dutinfo DUT Informatique 2005 USMB
lpbdd Licence professionnelle Bases de données 2011 USMB
Auto-
sic Master Informatique et Systèmes coopératifs 2005 USMB
généré
irc Informatique et réseaux de communication 2007 CPE
ics Informatique et CyberSécurité 2019 CPE

1ère modélisation : stockage de l’objet ou d’une partie de l’objet

Collection etudiants qui contient l’objet (ou une partie de l’objet) formations :

Avantages Inconvénients
Pas besoin de jointure => rapide en lecture Si un intitulé de formation change, il faut modifier
tous les étudiants ayant cet intitulé (par exemple
DUT -> BUT) => peu rapide en MaJ
Volume de données plus important

Ajouter un champ formation, contenant l’ID et l’intitulé, aux étudiants. Vous pourrez utiliser la
commande db.collection.updateOne (ou updateMany) pour mettre à jour un seul / plusieurs
enregistrements) ou db.collection.findAndModify ou db.collection.findOneAndUpdate.
Indications :
- Vous n’êtes pas sensé connaitre l’ID auto-généré de la formation. Une première requête doit
récupérer une formation donnée (_id et intitule).
var formation=db.formations.find(…).toArray();

Pour voir le contenu d’une variable, il suffit de faire :
var formation=db.formations.find(…).toArray();
formation

- Une 2nde requête met à jour les étudiants en fonction de la formation récupérée. Vous pourrez
créer un code « dynamique » de la façon suivante :
var etudiants = db.etudiants.find(…).toArray();
for (var index = 0; index < etudiants.length; index++) {
switch (index%4) {
case 0: db.etudiants.updateOne(…)
break;

Vincent COUTURIER 12
}
}
- Afin de répondre à la question 2.5, au moins 2 étudiants devront suivre la formation « DUT
Informatique ».

Ecrire une requête affichant les étudiants (nom, prénoms) et leur formation.

2nde modélisation : stockage de l’ID uniquement

Collection etudiants2 qui contient seulement l’ID des formations :

Avantages Inconvénients
Rapide en MaJ (si, par exemple, changement Peu rapide en lecture car nécessite une jointure
d’intitulé de la formation)
Volume de données plus réduit

Ajouter un champ formation, contenant uniquement l’ID, aux étudiants. Mêmes indications que
pour la section précédente.
ATTENTION, on doit obtenir ceci :
{

"formation" : ObjectId("60832a82ec1f4c2be651f239")
}
Et non :
{

"formation" : {
"_id" : ObjectId("60832a82ec1f4c2be651f239")
}
}

Ecrire une requête permettant de réaliser une « jointure » entre les 2 collections de 2
manières :
• En partant d’etudiants2
• En partant de formations
Vous n’afficherez que les nom, prénoms et formation pour chaque étudiant. Vous pourrez utiliser
les commandes $lookup, $replaceRoot et $project :
https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/
Dans la clause $project, vous mettrez tous les champs que vous souhaitez cacher à 0 (ou false).
Exemple de résultat que vous devez obtenir :
{
intitule: 'DUT Informatique',
nom: 'DURAND',
prenoms: [
'Alain',
'Paul'
]
}

{
Vincent COUTURIER 13
intitule: 'Informatique et CyberSécurité',
nom: 'EVENOT',
prenoms: [
'Vincent',
'Paul'
]
}

2.5. Transactions

Ecrire le code permettant de créer :


• Une transaction qui permet l’insertion :
o D’une formation
o ET de 2 étudiants de cette formation dans la collection etudiants2
• Une transaction qui permet la modification :
o De la formation « DUT Informatique » en « BUT Informatique » (modifier le sigle également
pour 'butinfo')
o ET de tous les intitulés dans la collection etudiants

Transactions MongoDB :
• https://dzone.com/articles/mongodb-transactions-your-very-first-transaction-w
• https://docs.mongodb.com/manual/core/transactions/

ATTENTION, Pour le lancement en mode ReplicaSet, suivre les indications suivantes :


Fermer le client Mongo (Robo3T) puis arrêter le serveur Mongo.
Relancer le serveur en mode ReplicaSet :

Lancer ensuite le Shell Mongo LINUX : ./mongo

Vincent COUTURIER 14
Executer rs.initiate()

Pour passer du replica secondaire au primaire, saisir rs.status()

Vous devez obtenir ceci :

Lancer ensuite Robo3t et écrire votre code.

Vincent COUTURIER 15
3. Outils d’administration

Ne pas arrêter le serveur.

Les outils suivants sont situés dans le dossier /mongodb/bin :

• Sauvegarde :
o Lancer la commande mongodump : ./mongodump
Plus de détails sur la commande :
https://docs.mongodb.com/database-tools/mongodump/
o La base de données a été sauvegardée.

o Visualiser le contenu des fichiers générés dans le dossier bdetudiants

• Restauration :
o Exemple : restauration des données dans une nouvelle base nommée bdetudiants2

Plus de détails sur la commande :


https://docs.mongodb.com/database-tools/mongorestore/
o Visualiser les données dans Robo 3T

• Autres outils intéressants :


o bsondump : https://docs.mongodb.com/database-tools/bsondump/
o mongoimport : https://docs.mongodb.com/database-tools/mongoimport/
o mongoexport : https://docs.mongodb.com/database-tools/mongoexport/

Les tester. Ecrire les commandes et expliquer leur utilité.

4. JSON schema

Un schéma permet d’ajouter des contraintes sur les champs (contraintes de types de données, de valeurs
possibles, etc.).

Vincent COUTURIER 16
Ouvrir le fichier movies_references_exporte.json et regarder son contenu. Ce fichier Json contient des
films.

En vous basant sur https://docs.mongodb.com/manual/reference/operator/query/jsonSchema/, réaliser le


schéma du fichier Json puis créer la collection movies dans une nouvelle base de données.
Indications à prendre en compte :
- Champs requis : _id, genre, title, year, country, director
- actors : tableau d’object. Nombre maximum d’acteurs dans le tableau : 6
- year : entre 1950 et 2019
- country : valeurs possibles : USA, FR, IT, DE

Tester ensuite l’importation en utilisant l’outil mongoimport. Commande :

Créer des documents Json ne respectant pas le schéma et qui généreront des erreurs :

5. Indexation et plan d’exécution

Indexation :
• https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/
• https://docs.mongodb.com/manual/reference/method/db.collection.getIndexes/
• https://docs.mongodb.com/manual/reference/method/db.collection.totalIndexSize/
• https://docs.mongodb.com/manual/reference/method/db.collection.reIndex/
Explain : https://docs.mongodb.com/manual/reference/method/db.collection.explain/
Validation (à utiliser avant et après la création d’index pour pouvoir comparer) :
https://docs.mongodb.com/manual/reference/method/db.collection.validate/
Statistiques : https://docs.mongodb.com/manual/reference/method/db.collection.stats/

A vous de tester et d’expliquer sur la collection des films (car il y a plus de données) :

Comme les SGBD relationnels, les index MongoDB sont basés sur des B-Tree. Principaux types d’index (A
expliquer, vous pourrez ajouter du code testant ces index) :
• Les index primaires :

Vincent COUTURIER 17
• Les index simples :

• Les index composés :

• Les index MultiKey :

• Les index texte :

• Index géo-spatiaux (2d, 2dsphere) :

• Les index hachés :

Ces index possèdent des options :


• TTL : Time To Live.

• Unique :

• Partiel :

• Epars (Sparse) :

• Insensibilité́ à la casse :

Les index doivent pouvoir tenir en RAM dans un cluster MongoDB, afin d'avoir des performances optimales
: https://docs.mongodb.com/manual/tutorial/ensure-indexes-fit-ram/

6. Interface REST

Dans la machine virtuelle, installer l’interface REST Eve :


sudo apt update
sudo apt install python3-pip
pip3 install eve --user

En suivant le tutoriel (https://docs.python-eve.org/en/stable/quickstart.html#a-minimal-application)


réaliser une API permettant de requêter soit les données des étudiants, soit celles des films (Question
4).

Exemples pour les étudiants :


- Recherche d’un étudiant par son nom :

Vincent COUTURIER 18
Dans le cas des films, la recherche se fera sur le titre.

- Affichage de tous les étudiants :

Remarque : ici, nous n’avons affiché que les nom, prénoms et adresse de chaque étudiant.

Dans le cas des films, vous n’afficherez que les titre, genre et rôles.

Rendre le code Python.

Vincent COUTURIER 19

Vous aimerez peut-être aussi