Cours 3 (Partie 2) Mongodb

Télécharger au format pdf ou txt
Télécharger au format pdf ou txt
Vous êtes sur la page 1sur 59

Institut Supérieur d’Informatique - Université Tunis El Manar

Cours 3 (Partie 2)
MongoDB

Riadh ZAAFRANI
Novembre 2022
Mastère professionnel Développement logiciel
et Nouvelles technologie (MDL) - M1

Plan
◼ Introduction
◼ Modélisation Objet JSON
◼ Installation
◼ Présentation de MongoDB
◼ Requêtes MongoDB
◼ Le modèle MapReduce
◼ Frameworks MapReduce : MongoDB
2

◼ Conclusion
2

1
Introduction
◼ Dans ce cours nous manipulerons les grands
ensembles de documents organisés en bases de
données comme ça existe sur le Web.
◼ Le Web n’est pas vraiment une base de données
mais c’est un système distribué de documents, et un
cas-type de Big Data s’il en est.
◼ De plus, il s’agit d’une source d’information
essentielle pour collecter des données, les agréger
et les analyser.
◼ Le système NoSQL qui sera présenté est MongoDB
pour JSON. 3

Introduction
◼ MongoDB est développé depuis 2007 par MongoDB.
◼ Cette entreprise travaillait alors sur un système de
Cloud computing, informatique à données largement
réparties, similaire au service Google App Engine de
Google.
◼ Sa première version considérée comme
industriellement viable a été la 1.4, en 2010.
◼ MongoDB est une base de données open source
orientée documents qui fournit de hautes
performances, une haute disponibilité, et mise à
l'échelle automatique. 4

2
Plan
◼ Introduction
◼ Modélisation Objet JSON
◼ Installation
◼ Présentation de MongoDB
◼ Requêtes MongoDB
◼ Le modèle MapReduce
◼ Frameworks MapReduce : MongoDB
5

◼ Conclusion
5

Définition d’un objet JSON


◼ JSON est un format de représentation logique de
données, hérité de la syntaxe de création d'objets
en JavaScript.
◼ C'est un format réputé léger (il ne contient pas
trop de caractères de structuration), assez
facilement lisible par les humains, facilement
parsable par les machines, et indépendant des
langages qui l'utilisent (sa seule fonction est de
décrire des données, qui sont ensuite utilisées
différemment pour chaque cas suivant le
contexte). 6

3
Définition d’un objet JSON
◼ Les documents dans MongoDB sont des objets
JSON. Un enregistrement JSON est un
document, qui est une structure de données
champ-valeur. Les valeurs d'un champ peuvent
inclure d'autres documents, des tableaux, ou
même des tableaux de documents.
{
matricule: “08p037”,
nom: “Ben Ahmed”,
classe: “1Master-Info”,
club: [“Microsoft”, “ENACTUS”, “Freeways”]
} 7

La syntaxe JSON en bref


◼ Un fichier au format JSON a pour extension ".json".
◼ Il ne doit exister qu'un seul élément père par document
contenant tous les autres : un élément racine.
◼ Tout fichier JSON bien formé doit être :
◼ soit un objet commençant par { et se terminant par },
◼ soit un tableau commençant par [ et terminant par ].
◼ Cependant ils peuvent être vides, ainsi [] et {} sont des
JSON valides.
◼ Les séparateurs utilisés entre deux paires/valeurs sont des
virgules.
◼ Un objet JSON peut contenir d'autres objets JSON.
◼ Il ne peut pas y avoir d'éléments croisés. 8

4
Éléments du format JSON
◼ Il existe deux types d'éléments :
◼ Des couples de type "nom": valeur,
comme l'on peut en trouver dans les
tableaux associatifs.
◼ Des listes de valeurs, comme les
tableaux utilisés en programmation.

Éléments du format JSON


◼ Il existe deux types d'éléments :
◼ Des couples de type "nom": valeur, comme l'on peut en
trouver dans les tableaux associatifs.
◼ Des listes de valeurs, comme les tableaux utilisés en
programmation.
◼ Valeurs possibles :
◼ Primitifs : nombre, booléen, chaîne de caractères, null.
◼ Tableaux : liste de valeurs (tableaux et objets aussi
autorisés) entrées entre crochets, séparées par des
virgules.
◼ Objets : listes de couples "nom": valeur (tableaux et
objets aussi autorisés) entrés entre accolades, séparés 10

par des virgules.


10

5
Exemple au format JSON
1{
17 {
2 "nom cours" : "BDA",
18 "nom" : "Ourson",
3 "theme" : "ingenierie documentaire",
19 "prenom" : "Winnie",
4 "etudiants" : [
20 "age" : 10,
5{
21 "pays" : "France"
6 "nom" : "Norris",
22 }
7 "prenom" : "Chuck",
23 ]
8 "age" : 73,
24 }
9 "pays" : "USA"
10 },
11 {
12 "nom" : "Doe",
13 "prenom" : "Jane",
14 "age" : 45,
15 "pays" : "Angleterre" 11

16 },
11

QUIZ

◼ Qu'est-ce que le JSON ?

❑ Un langage de programmation orientée objet.


❑ Un type de pages web.
❑ Un format qui permet de décrire des données
structurées.
❑ Une catégorie de documents générés par un
traitement de texte

12

12

6
QUIZ

◼ Un fichier JSON doit forcément être traité


via du code JavaScript.

❑ Vrai

❑ Faux

13

13

QUIZ

◼ On peut utiliser des tableaux en JSON et en


XML.

❑ Vrai
❑ Faux, on ne peut le faire qu'en XML
❑ Faux, on ne peut le faire qu'en JSON
❑ Faux, on ne peut le faire ni en XML ni en JSON

14

14

7
Plan
◼ Introduction
◼ Modélisation Objet JSON
◼ Installation
◼ Présentation de MongoDB
◼ Requêtes MongoDB
◼ Le modèle MapReduce
◼ Frameworks MapReduce : MongoDB
15

◼ Conclusion
15

Installation
◼ MongoDB est un système libre de droits (pour sa version de
base), téléchargeable à :
https://www.mongodb.com/try/download/community

◼ Télécharger la dernière
version stable
correspondant à votre
système d’exploitation et
décompressez ensuite
l’archive récupérée ou
bien suivez les étapes
d'installation :
16

16

8
Configuration de
l'environnement MongoDB
◼ Une fois l’installation terminée, vous obtenez un répertoire
nommé mongo, agrémenté du numéro de version et autres
indicateurs. Par exemple : C:\Program
Files\MongoDB\Server\6.0. Vous devriez ajouter C:\Program
Files\MongoDB\Server\6.0\bin; dans la variable
d’environnement PATH.
◼ MongoDB nécessite un
répertoire pour stocker toutes
les données. Par défaut, le
chemin de ce répertoire
est: C:\Program
Files\MongoDB\Server\6.0\data\
17

17

Configuration de
l'environnement MongoDB
◼ A partir de la version 6, vous
devez aussi télécharger le
MongoDB Shell à partir de
la page :
https://www.mongodb.com/tr
y/download/shell
◼ Vous devez le
décompresser et le placer
dans la racine du repertoire
C et ajouter son chemin
dans la variable
18
d’environnement PATH.
18

9
Configuration de
l'environnement MongoDB
◼ MongoDB fonctionne en mode classique
client/serveur. Pour lancer le serveur, exécutez
simplement la commande mongod qui se trouve
dans bin, et c’est tout.
◼ Vous devez d’abord spécifier un autre chemin pour
les fichiers de données en créant le dossier :
"C:\data\db“

19

19

Lancement de MongoDB
◼ Pour lancer MongoDB, il faudra donc d’abord lancer
le serveur via l'invite de commandes : mongod.
◼ Si tout se passe bien, le démarrage du serveur se
concrétise pas des messages divers se terminant
par : [initandlisten] waiting for connections on
port 27017 qui indique que le processus
mongod.exe a bien été exécuté.
◼ Le serveur mongod est donc en attente sur le port
27017. Il traite les requêtes sur les données, gère
l'accès aux données, et effectue des opérations de
traitement en arrière-plan. 20

20

10
Le client Mongo
◼ Maintenant, il nous faut une application cliente.
◼ Nous avons en gros deux possibilités :
L’interpréteur de commande mongo ou une
application graphique plus agréable à utiliser.
◼ Parmi ces dernières, deux choix
recommandables sont RockMongo, une
application Web d’administration de MongoDB à
peu près équivalente à phpMyAdmin, et
RoboMongo, plus facile d’installation.
21

21

Le client RoboMongo
◼ RoboMongo est un
client graphique
disponible pour toutes
les plate-formes à
robomongo.org.
◼ C’est sans doute le
choix à privilégier.
l’installation est très
simple, l’outil semble
assez complet et en
évolution rapide. 22

22

11
Le client RoboMongo

23

23

Plan
◼ Introduction
◼ Modélisation Objet JSON
◼ Installation
◼ Présentation de MongoDB
◼ Requêtes MongoDB
◼ Le modèle MapReduce
◼ Frameworks MapReduce : MongoDB
◼ Conclusion 24

24

12
Présentation de MongoDB
◼ MongoBD est une base de données open
source NoSQL orientée document. Elle stocke
des données au format JSON (en fait BSON, qui
est une version binaire de JSON).
◼ Le serveur MongoDB est organisé en plusieurs
databases :
◼ Chaque database contient des collections.
◼ Chaque collection contient des documents.
◼ Chaque document est au format JSON et
contient donc des propriétés. 25

25

Présentation de MongoDB

◼ C'est une base schema-less. Une collection peut contenir


des documents de structures différentes et il n'est pas
possible de définir la structure a priori d'une collection.
◼ La structure d'une collection n'est donc définie que par les
documents qui la compose, et elle peut évoluer
dynamiquement au fur et à mesure des insertions et 26
suppressions.
26

13
Présentation de MongoDB
Identification clé / valeur
◼ Chaque document est identifié par un identifiant
nommé _id unique pour une collection, fonctionnant
comme une clé primaire artificielle.
Architecture
◼ MongoDB fonctionne a minima sous la forme d'un
serveur auquel il est possible de se connecter avec
un client textuel (mongo shell).
◼ MongoDb peut être distribuée sur plusieurs serveurs
(partitionnement horizontal ou sharding) et accédée
à travers de multiples couches applicatives
(langages, API...) 27

27

Le client Mongo (mongo shell)


◼ Pour se connecter à MongoDB, en utilisant l’interpréteur de
commande (mongo shell), ouvrez une nouvelle fenêtre
d'invite de commandes et tapez la commande mongosh.

28

28

14
Le client Mongo (mongo shell)
◼ La connexion ne peut réussir que si le service
MongoDB est lancé.
◼ Par défaut, mongosh recherche un serveur de
base de données sur le port 27017 sur
l'interface locale.
◼ Pour se connecter à un serveur sur un port ou
une interface différente, utilisez les
paramètres --port et --host.
29

29

Le client Mongo (mongo shell)


◼ Après le lancement de mongosh, votre
session va utiliser par défaut la base de
données « test ».
◼ L’outil mongosh est en fait un
interpréteur javascript (ce qui est
cohérent avec la représentation JSON)
et on peut donc lui soumettre des
instructions en Javascript, ainsi que des
commandes propres à MongoDB. 30

30

15
Le client Mongo (mongo shell)
◼ Voici quelques instructions de base :
➢ db : pour avoir le nom de la base de données
courante.
➢ show databases : pour avoir la liste des bases
de données.
➢ use <database>: pour se placer dans une base.
➢ Help : pour afficher l'aide.

31

31

Création d'une collection et


insertion de documents
◼ Une base est donc constituée d’un ensemble de
collections, l’équivalent d’une table en relationnel.
◼ Pour créer une collection : db.createCollection("groupes")
◼ La liste des collections est obtenue par : show collections
◼ Pour insérer un document JSON dans une collection (ici,
groupes) :
➢ db.groupes.insertOne ({"nom": "1 Master Info"})
◼ Il existe donc un objet (javascript) implicite, db, auquel on
soumet des demandes d’exécution de certaines
méthodes.
32

32

16
Création d'une collection et
insertion de documents
◼ Pour afficher le contenu d’une collection :
➢ db.groupes.find()
◼ C’est un premier exemple d’une fonction de recherche avec MongoDB.
On obtient des objets (javascript, encodés en JSON) { "_id" :
ObjectId("5de2282d319c52285f46d661"), "nom" : "1 Master info" }
◼ MongoDB associe un identifiant unique à chaque document, de nom
conventionnel _id, et lui attribue une valeur si elle n’est pas indiquée
explicitement.

33

33

Création d'une collection et


insertion de documents
◼ Pour insérer un autre document :
➢ db.groupes.insert ({"produit": "Stylo", prix: 900, enStock:
true})
◼ Vous remarquerez que la structure de ce document n’a
rien à voir avec le précédent : il n’y a pas de schéma (et
donc pas de contrainte) dans MongoDB. On est libre de
tout faire (et même de faire n’importe quoi).
◼ Nous sommes partis pour mettre n’importe quel objet
dans notre collection groupes, ce qui revient à reporter
les problèmes (contrôles, contraintes, tests sur la
structure) vers l’application.
34

34

17
Création d'une collection et
insertion de documents
◼ On peut affecter un identifiant explicitement :
➢ db.groupes.insert ({_id: "1", "produit": "Crayon", prix:
400, enStock: true})
◼ On peut compter le nombre de documents dans la
collection :
➢ db.groupes.countDocuments()
◼ Et finalement, on peut supprimer une collection :
➢ db.groupes.drop()

35

35

Création de la base
◼ Nous allons insérer des documents plus sérieux pour
découvrir les fonctionnalités de MongoDB.
◼ Pour cela, nous travaillerons sur une base contenant des
films complets téléchargeable à :
http://webscope.bdpedia.fr/

36

36

18
Création de la base
◼ Notre base de films nous fournit des documents JSON,
comme celui-ci par exemple :
◼ {
"_id": "movie:100",
"title": "The Social network",
"summary": "On a fall night in 2003, Harvard undergrad and
programming genius Mark Zuckerberg sits down at his
computer and heatedly begins working on a new idea. (...)",
"year": 2010,
"director": {"last_name": "Fincher","first_name": "David"},
"actors": [ {"first_name": "Jesse", "last_name": "Eisenberg"},
{"first_name": "Rooney", "last_name": "Mara"} ]
} 37

37

Création de la base
[
◼ Comme il serait fastidieux de {
"_id": "movie:1",
les insérer un par un, nous "title": "Vertigo",
"year": "1958",
allons utiliser l’utilitaire "director": {
d’import de MongoDB. Il "_id": "artist:3",
"last_name": "Hitchcock",
prend en entrée un tableau "first_name": "Alfred",
JSON contenant la liste des "birth_date": "1899 » },
"actors": [
objets à insérer. { "_id": "artist:15",
"first_name": "James",
◼ Dans notre cas, nous allons "last_name": "Stewart",
},
utiliser l’export JSON de la {"_id": "artist:16",
base Webscope dont le "first_name": "Kim",
"last_name": "Novak",} ] },
format est le suivant. {"_id": "movie:2",
"title": "Alien", 38
…}
]
38

19
L’outil mongoimport
◼ À partir de MongoDB 4.4,
mongoimport est déployé
séparément du serveur
MongoDB.
◼ mongoimport fait partie des outils
: The MongoDB Database Tools.
C’est une collection d'utilitaires
(ligne de commande) travaillant
sur des bases MongoDB.
◼ Il permet d’importer des contenus
en JSON, CSV ou TSV.
◼ mongoimport et tous les outils
MongoDB peuvent être
téléchargés à partir du Centre de 39

téléchargement MongoDB.
39

Création de la base
◼ En supposant que ce tableau est sauvegardé dans
movies.json, on peut importer la liste des films complets dans
la collection movies de la base test avec la commande
suivante directement à partir de l’interpréteur des
commandes :
◼ mongoimport -d test -c movies --file movies.json --jsonArray

◼ Ne pas oublier l’argument jsonArray qui indique à l’utilitaire


d’import qu’il s’agit d’un tableau d’objets à créer
individuellement, et pas d’un unique document JSON. 40

40

20
Création de la base
◼ Pour importer la liste des artistes dans la collection artists de
la base test, on utilisera la commande :
◼ mongoimport -d test -c artists --file artists.json --jsonArray

◼ Enfin, pour importer la liste des films avec les références aux artistes
dans la collection moviesRefs de la base test, on utilisera la
commande :
◼ mongoimport -d test -c moviesRefs --file movies-refs.json --jsonArray

41

41

Plan
◼ Introduction
◼ Modélisation Objet JSON
◼ Installation
◼ Présentation de MongoDB
◼ Requêtes MongoDB
◼ Le modèle MapReduce
◼ Frameworks MapReduce : MongoDB
◼ Conclusion
42

42

21
Requêtes MongoDB
◼ Comme nous l’avons vu :
◼ MongoDB n’impose pas de schéma, ce qui peut être
vu comme un avantage initialement, mais s’avère
rapidement pénalisant puisque la charge du contrôle
des données est reportée du côté de l’application ;
◼ MongoDB propose un langage d’interrogation qui lui
est propre (donc, non standardisé), pratique mais
limité ;
◼ enfin MongoDB n’offre aucun support
transactionnel.
43

43

Requêtes MongoDB
◼ Le langage de requête sur des collections
est spécifique à MongoDB.
◼ C’est un langage de recherche dit “par
motif” (pattern) : Il consiste à interroger
une collection en donnant un objet (le
“motif/pattern”, en JSON) dont chaque
attribut est interprété comme une contrainte
sur la structure des objets à rechercher.
44

44

22
Sélections
◼ Commençons par la base : on veut parcourir
toute une collection. On utilise alors find()
dans argument.
➢ db.movies.find()
◼ Pour améliorer l’affichage, on peut utiliser la
commande pretty : db.movies.find().pretty()
◼ Si je souhaite afficher les documents
suivants, il me suffit de taper it.
45

45

Sélections
◼ S’il y a des millions de documents, cela risque
de prendre du temps... D’ailleurs, comment
savoir combien de documents comprend le
résultat ?
➢ db.movies.countDocuments()
ou
➢ db.movies.count()

46

46

23
Sélections
◼ Comme en SQL (étendu), les options skip et limit
permettent de “paginer” le résultat. La requête
suivante affiche 12 documents à partir du dixième
inclus.
➢ db.movies.find().skip(9).limit(12)
◼ Implicitement, cela suppose qu’il existe un ordre
sur le parcours des documents.
◼ Par défaut, cet ordre est dicté par le stockage
physique : MongoDB fournit les documents dans
l’ordre où il les trouve (dans les fichiers).
47

47

Sélections
◼ On peut trier explicitement, ce qui rend le résultat
plus déterministe. La requête suivante trie les
documents sur le titre du film, puis pagine le
résultat.
➢ db.movies.find().sort({"title":1}).skip(9).limit(12)
◼ La spécification du tri repose sur un objet JSON, et
ne prend en compte que les noms d’attributs sur
lesquels s’effectue le tri.
◼ La valeur (ici, celle du titre) sert à indiquer si on trie
de manière ascendante (valeur 1) ou descendante
(valeur -1). 48

48

24
Sélections
◼ Attention, trier n’est pas anodin.
◼ En particulier, tout tri implique que le système
constitue l’intégralité du résultat au préalable,
ce qui induit une latence (temps de réponse)
potentiellement élevée.
◼ Sans tri, le système peut délivrer les
documents au fur et à mesure qu’il les trouve.

49

49

Critères de recherche
◼ Si on connaît l’identifiant, on effectue la recherche
ainsi :
➢ db.movies.find ({"_id": "movie:2"})
◼ Une requête sur l’identifiant ramène (au plus) un seul
document. Dans un tel cas, on peut utiliser findOne :
➢ db.movies.findOne ({"_id": "movie:2"})
◼ Cette fonction renvoie toujours un document (au plus),
alors que la fonction find renvoie un curseur sur un
ensemble de documents (même si c’est un singleton).
La différence est surtout importante quand on utilise
une API pour accéder à MongoDB avec un langage 50

de programmation.
50

25
Critères de recherche
◼ Sur le même modèle, on peut interroger n’importe
quel attribut.
➢ db.movies.find ({"title": "Alien"})
◼ Ça marche bien pour des attributs atomiques (une
seule valeur), mais comment faire pour interroger
des objets ou des tableaux imbriqués ?

51

51

Critères de recherche
{ "_id" : "movie:14",
◼ On utilise dans ce cas des "title" : "Seven",
"year" : 1995,
chemins, un peu à la XPath, "genre" : "crime", "summary" :
"A New York, un criminel anonyme
mais avec une syntaxe plus a décidé de commettre 7 meurtres
“orienté-objet”. basés.... ",
"country" : "USA",
◼ Voici comment on recherche "director" : {
"_id" : "artist:31",
les films de David Fincher. "last_name" : "Fincher",
"first_name" : "David",
➢ db.movies.find "birth_date" : "1962" },
"actors" : [ {
({"director.last_name": "_id" : "artist:18",
"first_name" : "Kevin",
"Fincher"}) "last_name" : "Spacey",
"birth_date" : "1959", "role" :
"Doe"
◼ }…. ]} 52

52

26
Critères de recherche
{ "_id" : "movie:14",
◼ Et pour les acteurs, qui sont "title" : "Seven",
"year" : 1995,
eux-mêmes dans un tableau "genre" : "crime", "summary" :
"A New York, un criminel anonyme
? Ca fonctionne de la même a décidé de commettre 7 meurtres
manière. basés.... ",
"country" : "USA",
➢ db.movies.find "director" : {
"_id" : "artist:31",
({"actors.last_name": "last_name" : "Fincher",
"first_name" : "David",
"Spacey"}) "birth_date" : "1962" },
"actors" : [ {
◼ La requête s’interprète donc "_id" : "artist:18",
"first_name" : "Kevin",
comme : “Tous les films dont "last_name" : "Spacey",
"birth_date" : "1959", "role" :
l’un des acteurs se nomme "Doe"
Spacey”. ◼ }…. ]} 53

53

Critères de recherche
◼ Conformément aux principes du semi-structuré, on accepte
sans protester la référence à des attributs ou des chemins
qui n’existent pas.
◼ En fait, dire “ce chemin n’existe pas” n’a pas grand sens
puisqu’il n’y a pas de schéma, pas de contrainte sur la
structure des objets, et que donc tout chemin existe
potentiellement : il suffit de le créer.
◼ La requête suivante ne ramène rien, mais ne génère pas
d’erreur.
➢ db.movies.find ({"actor.last_name": " Spacey"})
◼ Important : Contrairement à une base relationnelle, une base
semi-structurée ne proteste pas quand on fait une faute de
54
frappe sur des noms d’attributs.

54

27
Critères de recherche
◼ Quelques raffinements permettent de dépasser la limite sur le
prédicat d’égalité implicitement utilisé ici pour comparer les
critères donnés et les objets de la base.
◼ Pour les chaînes de caractères, on peut introduire des
expressions régulières.
◼ Tous les films dont le titre commence par Re ?
➢ db.movies.find ({"title": /^Re/}, {"actors": 0, "summary": 0} )
◼ Pas d’apostrophes autour de l’expression régulière.
◼ On peut aussi effectuer des recherches par intervalle.
◼ db.movies.find( {"year": {$gte: 2000, $lte: 2005} },{"title": 1})
◼ Il n’est pas possible d’utiliser les signes habituels (>, >=, <,
<=, !=). MongoDB propose à la place des opérateurs dédiés55
($gt, $gte, $lt, $lte, $ne).
55

Projections
◼ Jusqu’à présent, les requêtes ramènent l’intégralité
des objets satisfaisant les critères de recherche.
◼ On peut aussi faire des projections, en passant un
second argument à la fonction find() :
➢ db.movies.find ({"actors.last_name": "Tarantino"},
{"title": true, "actors": 5} )
◼ Le second argument est un objet JSON dont les
attributs sont ceux à conserver dans le résultat.
56

56

28
Projections
◼ La valeur des attributs dans cet objet-projection ne
prend que deux interprétations : Toute valeur autre
que 0 indique que l’attribut doit être conservé. Si
on choisit au contraire d’indiquer les attributs à
exclure, on leur donne la valeur 0.
◼ Par exemple, la requête suivante retourne les films
sans les acteurs et sans le résumé.
➢db.movies.find ({"actors.last_name": "Tarantino"},
{"actors": 0, "summary": 0})
57

57

Projections
◼ Dans une projection, la requête renvoie également
le champ _id. C’est le fonctionnement normal de
la commande find qui renvoie systématiquement
la clé du document.
◼ Si l’on souhaite l’exclure, il faut le préciser dans la
commande.
➢db.movies.find ({"actors.last_name": "Tarantino"},
{"title": 1, "actors": 1, "_id" : 0})
58

58

29
Opérateurs ensemblistes
◼ Les opérateurs du langage SQL in, not in, any et all se
retrouvent dans le langage d’interrogation.
◼ La différence, notable, est que SQL applique ces opérateurs
à des relations (elles-mêmes obtenues par des requêtes)
alors que dans le cas de MongoDB, ce sont des tableaux
JSON.
◼ MongoDB ne permet pas d’imbriquer des requêtes.
◼ Voici un premier exemple : on cherche les films dans
lesquels joue au moins un des artistes dans une liste (on
suppose que l’on connaît l’identifiant).
➢db.movies.find({"actors._id": {$in: ["artist:34","artist:98","artist:1"]}})
59

59

Opérateurs ensemblistes
◼ Gardez cette recherche en mémoire : elle s’avèrera
utile pour contourner l’absence de jointure en
MongoDB. Le in exprime le fait que l’une des valeurs
du premier tableau (actors._id) doit être égale à l’une
des valeurs de l’autre. Il correspond implicitement, en
SQL, à la clause any.
◼ Pour exprimer le fait que toutes les valeurs du premier
tableau se retrouvent dans le second (en d’autres
termes, une inclusion), on utilise la clause all.
➢db.movies.find({"actors._id": {$all: ["artist:23","artist:147"]}})
60

60

30
Opérateurs ensemblistes
◼ Le not in correspond à l’opérateur $nin.
➢ db.movies.find({"actors._id": {$nin:
["artist:11","artist:14","artist:15"]}})
◼ Comment trouver les titres des films qui
n’ont pas d’attribut summary ?
➢ db.movies.find({"summary": {$exists:
false}}, {"title": 1})
61

61

Opérateurs Booléens
◼ Par défaut, quand on exprime plusieurs
critères, c’est une conjonction (and) qui est
appliquée. On peut l’indiquer explicitement.
◼ Voici la syntaxe (les films tournés avec
Leonardo DiCaprio en 1997) :
➢ db.movies.find( { $and : [ {"year": 1997},
{"actors.last_name": "DiCaprio"} ] } )
◼ L’opérateur and s’applique à un tableau de
conditions.
62

62

31
Opérateurs Booléens

◼ Bien entendu, il existe un opérateur or


avec la même syntaxe.
◼ Les films parus en 1997 ou avec
Leonardo DiCaprio.
➢ db.movies.find({$or : [ {"year": 1997},
{"actors.last_name": "DiCaprio"} ] } )

63

63

Jointures
◼ Voici pour l’essentiel en ce qui concerne les
recherches portant sur une collection et
consistant à sélectionner des documents.
◼ Grosso modo, on obtient la même
expressivité que pour SQL dans ce cas. Que
faire quand on doit croiser des informations
présentes dans plusieurs collections ? En
relationnel, on effectue des jointures.
◼ Avec Mongo, il faut bricoler.
64

64

32
Jointures
◼ La jointure, au sens de : associer des objets
distincts, provenant en général de plusieurs
collections, pour appliquer des critères de recherche
croisés, n’existe pas en MongoDB.
◼ C’est une limitation très importante du point de vue
de la gestion de données. On peut considérer
qu’elle est cohérente avec une approche
documentaire dans laquelle les documents sont
supposés indépendants les uns des autres, avec
une description interne suffisamment riche pour que
toute recherche porte sur le contenu du document 65
lui-même.
65

Jointures
◼ Cela étant, on peut imaginer toutes sortes de
situations où une jointure est nécessaire dans une
application de traitement de données. Le serveur ne
sachant pas effectuer de jointures, on en est réduit à
les faire côté client, comme illustré sur la figure :

66

66

33
Jointures
◼ Cela revient essentiellement à appliquer l’algorithme
de jointures par boucle imbriquées en stockant des
données temporaires dans des structures de
données sur le client, et en effectuant des échanges
réseaux entre le client et le serveur, ce qui dans
l’ensemble est inefficace.
◼ Comme l’interpréteur mongo permet de programmer
en Javascript, nous pouvons en fait illustrer la
méthode assez simplement.
◼ Considérons la requête : “Donnez tous les films
dont le directeur est Clint Eastwood”. 67

67

Jointures
◼ Nous travaillons sur une base dans laquelle un
film ne contient que la référence au metteur en
scène, ce qui évite les redondances, mais
complique la reconstitution de l’information.
◼ La première étape dans la jointure côté client
consiste à chercher l’artiste Clint Eastwood et à
le stocker dans l’espace mémoire du client (dans
une variable, pour dire les choses simplement).
➢ eastwood = db.artists.findOne({"first_name":
"Clint", "last_name": "Eastwood"}) 68

68

34
Jointures
◼ On dispose maintenant d’un objet eastwood. Une
seconde requête va récupérer les films dirigés par
cet artiste.
➢ db.moviesRefs.find({"director._id": eastwood[’_id’]},
{"title": 1})
◼ Voilà le principe. Voyons maintenant plus
généralement comment on effectue l’équivalent des
jointures en SQL.
◼ Prenons la requête suivante :
➢ select m.titre, a.* from Movie m, Artist a
where m.id_director = a.id 69

69

Jointures
◼ On veut donc les titres des films et le réalisateur. On
va devoir coder, du côté client, un algorithme de
jointure par boucles imbriquées. Le voici, sous le
shell de MongoDB (et donc en programmation
javascript).
var lesFilms = db.moviesRefs.find();
while (lesFilms.hasNext()) {
var film = lesFilms.next();
var mes = db.artists.findOne({"_id": film.director._id});
printjson(film.title);
printjson(mes);
} 70

70

35
Jointures
◼ On a donc une boucle, et une requête
imbriquée, exécutée autant de fois qu’il y a de
films.
◼ C’est exactement la méthode qui serait utilisée
par le serveur si ce dernier implantait les
jointures.
◼ L’exécuter du côté client induit un surcoût en
programmation, et en échanges réseau entre
le client et le serveur.
71

71

Exercice : requêtes sur la base des films


◼ Tous les titres ;
◼ Tous les titres des films parus après 2000 ;
◼ Le résumé de Spider-Man ;
◼ Qui est le metteur en scène de Gladiator ?
◼ Titre des films avec Kirsten Dunst ;
◼ Quels films ont un résumé ?
◼ Les films qui ne sont ni des drames ni des
comédies.
72

72

36
Exercice : requêtes sur la base des films

◼ Affichez les titres des films et les noms des


acteurs.
◼ Dans quels films Clint Eastwood est-il acteur
mais pas réalisateur (aide : utilisez l’opérateur
de comparaison $ne).
◼ Difficile : Comment chercher les films dont le
metteur en scène est aussi un acteur ? Pas
sûr que ce soit possible sans recourir à une
auto-jointure, côté client...
73

73

Plan
◼ Introduction
◼ Modélisation Objet JSON
◼ Installation
◼ Présentation de MongoDB
◼ Requêtes MongoDB
◼ Le modèle MapReduce
◼ Découverte à l’aide d’un exemple
◼ Le modèle MapReduce en termes informatiques

◼ Frameworks MapReduce : MongoDB


74

◼ Conclusion
74

37
MapReduce
◼ Nous abordons maintenant un
processus plus complet pour le
traitement d’une collection, que nous
allons appeler chaîne de traitement par
traduction de “data processing
pipelines”.

75

75

MapReduce
◼ Le principe général est de soumettre chaque document
d’une collection à une séquence d’opérations, comme par
exemple :
➢ un filtrage, en ne gardant le document que s’il satisfait
certains critères ;
➢ une restructuration, en changeant la forme du document ;
➢ une annotation, par ajout au document de propriétés
calculées ;
➢ un regroupement avec d’autres documents sur certains
critères ;
➢ des opérations d’agrégation sur des groupes de
documents. 76

76

38
MapReduce
◼ La spécification d’une chaîne de traitement s’appuie
sur un paradigme nommé MapReduce que nous
rencontrerons de manière récurrente.
◼ Cette partie du cours propose une présentation
détaillée du principe de calcul MapReduce, avec
une illustration pratique avec MongoDB.
◼ MapReduce n’est vraiment intéressant que dans un
contexte distribué. Nous nous en tenons au
contexte centralisé (un seul serveur) dans ce cours,
ce qui permet de se familiariser avec les concepts et
la pratique dans un cadre simple. 77

77

Plan
◼ Introduction
◼ Modélisation Objet JSON
◼ Installation
◼ Présentation de MongoDB
◼ Requêtes MongoDB
◼ Le modèle MapReduce
◼ Découverte à l’aide d’un exemple
◼ Le modèle MapReduce en termes informatiques
◼ Frameworks MapReduce : MongoDB
78

◼ Conclusion
78

39
MapReduce démystifié
◼ Nous proposons une découverte “avec les mains”, en
étudiant comment cuisiner quelques recettes simples
avec un robot MapReduce.
◼ Vous savez faire du jus de pomme ? C’est simple :
◼ L’épluchage : il faut éplucher les pommes une par une ;
◼ Le pressage : on met toutes les pommes dans un
pressoir, et on récupère le jus.

79

79

Un jus de pomme MapReduce


◼ Comme notre but est de commencer à le formaliser en un
modèle que nous appellerons à la fin MapReduce, nous
distinguons la frontière entre les deux phases, et les
tâches effectuées de chaque côté.
◼ À gauche, nous avons donc l’atelier de transformation :
il consiste en un agent, l’éplucheur, qui prend une pomme
dans son panier à gauche, produit une pomme épluchée
dans un second panier à droite, et répète la même action
jusqu’à ce que le panier de gauche soit vide.
◼ À droite nous avons l’atelier d’assemblage : on lui confie
un tas de pommes épluchées et il produit du jus de
pomme. 80

80

40
Un jus de pomme MapReduce
◼ Nous pouvons déjà tirer deux leçons sur les caractéristiques
essentielles de notre processus élémentaire.
◼ La première porte sur l’atelier de transformation qui applique
une opération individuelle à chaque produit.
◼ Leçon 1 : l’atelier de transformation est centré sur les
pommes. Dans l’atelier de transformation, les pommes sont
épluchées individuellement et dans n’importe quel ordre.
◼ La seconde leçon porte sur l’atelier d’assemblage qui, au
contraire, applique une transformation aux produits
regroupés : ici, des tas de pommes.
◼ Leçon 2 : l’atelier d’assemblage est centré sur les tas de
pommes. Dans l’atelier d’assemblage, on applique des
81
transformations à des ensembles de pommes.
81

Un jus de pomme MapReduce


◼ Tout cela est assez élémentaire, voyons si nous
pouvons faire mieux en introduisant une première
variante. Au lieu de cuire des pommes entières, on
préfère les couper au préalable en quartiers.
◼ La phase d’épluchage devient une phase
d’épluchage/découpage.

82

82

41
MapReduce démystifié
◼ Cela ne change pas grand chose. Au lieu d’avoir deux tas
identiques à gauche et à droite avec des pommes, le cuisinier a un
tas avec p pommes à gauche et un autre tas avec 4p quartiers de
pommes à droite. Cela nous permet quand même de tirer une
troisième leçon.
◼ Leçon 3 : la transformation peut modifier le nombre et la nature des
produits. La première phase n’est pas limitée à une transformation
un pour un des produits consommés. Elle peut prendre en entrée
des produits d’une certaine nature (des pommes), sortir des produits
d’une autre nature (des quartiers de pomme épluchées), et il peut
n’y avoir aucun rapport fixe entre le nombre de produits en sortie et
le nombre de produits en entrée (on peut jeter des pommes
pourries, couper une pomme en 4 ou 6 ou 8, etc.) 83

83

Beaucoup de jus de pomme


◼ Nous avons ainsi notre premier processus
MapReduce, et nous avons identifié ses
caractéristiques principales.
◼ Il devient possible de montrer comment passer à
grande échelle dans la production de jus de
pomme, sans changer le processus.
◼ Votre jus de pomme est très bon et vous devez
en produire beaucoup : une seule personne ne
suffit plus à la tâche.
84

84

42
Beaucoup de jus de pomme
◼ Heureusement la méthode employée se généralise
facilement à une brigade de n cuisiniers.
➢ Répartissez votre tas de pommes en n sous-tas, affectés
chacun à un cuisinier ;
➢ Chaque cuisinier effectue la tâche d’épluchage/découpage
comme précédemment ;
➢ Regroupez les quartiers de pomme et pressez-les.
◼ Il se peut qu’un pressoir ne suffise plus : dans ce cas
affectez c pressoirs et répartissez équitablement les
quartiers dans chacun.
◼ Petit inconvénient : vous obtenez plusieurs fûts de jus de
pomme, un par pressoir, avec une qualité éventuellement 85
variable. Ce n’est sans doute pas très grave.
85

Beaucoup de jus de pomme


◼ Dans l’atelier de
transformation, vous avez n
cuisiniers qui, chacun, font
exactement la même chose
qu’avant : ils produisent des
tas de quartiers de pomme.
◼ Dans l’atelier d’assemblage,
vous avez r pressoirs : un au
minimum, 2, 3 ou plus selon
les besoins.
◼ Il n’y aucune raison d’imposer
comme contrainte que le
nombre de pressoirs soit égal 86

au nombre de cuisiniers.
86

43
Beaucoup de jus de pomme
◼ Vous avez ainsi parallélisé votre production de jus de
pomme.
◼ Vous pouvez même prétendre que la rentabilité économique
est préservée. Si un cuisinier épluche 50 Kgs de pomme par
jour, 10 cuisiniers (avec le matériel correspondant)
produiront 500 Kgs par jour !
◼ Nous dirons que le processus est scalable, et cela vaut une
quatrième leçon.
◼ Leçon 4 : parallélisation et scalabilité (linéaire). La
production de jus de pomme est parallélisable et
proportionnelle aux ressources (humaines et matérielles)
87
affectées.
87

Beaucoup de jus de pomme


◼ Le processus a une seconde caractéristique importante : Si
un cuisinier éternue à répétition sur son tas de pomme, s’il
épluche mal ou si les quartiers de pomme à la fin de
l’épluchage tombent par terre, cela ne remet pas en cause
l’ensemble de la production mais seulement la petite partie
qui lui était affectée. Il suffit de recommencer cette partie-
là. De même, si un pressoir est mal réglé, cela n’affecte pas
le jus de pomme préparé dans les autres et les dégâts restent
locaux.
◼ Leçon 5 : le processus est robuste. Une défaillance affectant
la production de jus de pomme n’a qu’un effet local et ne
remet pas en cause l’ensemble de la production. 88

88

44
Jus de fruits MapReduce
◼ Peut-on faire mieux que du jus de pomme ? Oui, si
vous avez une brigade d’éplucheurs de premier plan
et des pressoirs efficaces, vous pouvez aussi
envisager de produire du jus d’orange, du jus
d’ananas, et ainsi de suite.
◼ Le processus consistant en une double phase de
transformation individuelle des ingrédients, puis
d’élaboration collective convient tout à fait, à une
adaptation près : comme on ne peut pas presser
ensemble des oranges et les pommes, il faut ajouter
une étape initiale de tri/regroupement dans l’atelier
d’assemblage. 89

89

Jus de fruits MapReduce


◼ En revanche, pendant la première phase, on peut soumettre
un tas indifférencié de pommes/oranges/ananas à un même
cuisinier. L’absence de spécialisation garantit ici une
meilleure utilisation de votre brigade, une meilleure
adaptation aux commandes, une meilleure réactivité aux
incidents (pannes, blessures, etc.).

90

90

45
Jus de fruits MapReduce
◼ Une question non triviale est celle du critère de tri et de
regroupement. Dans le cas des pommes, oranges et ananas,
on peut supposer que l’opérateur fait facilement la distinction
visuellement.
◼ Pour des cas plus subtils il nous faut une méthode plus
robuste. Les produits fournis par l’atelier d’assemblage
doivent être étiquetés au préalable par l’opérateur de l’atelier
de transformation.
◼ Leçon 6 : phase de tri / regroupement, étiquetage. Si les
produits doivent être traitées par catégorie, il faut ajouter une
phase de tri / regroupement au début de l’atelier
d’assemblage. Le tri s’appuie sur une étiquette associée à
chaque produit en entrée, indiquant le groupe
d’appartenance. 91

91

Jus de fruits MapReduce


◼ Et finalement, comment faire si nous mettons en place
plusieurs ateliers d’assemblage ? Deux choix sont possibles :
➢ Spécialiser chaque atelier à une ou plusieurs catégories de
fruits ;
➢ Ne pas spécialiser les ateliers, où un atelier d’assemblage
sait presser tous les types de fruits.

92

92

46
Jus de fruits MapReduce
◼ Les deux choix se défendent sans doute, mais dans le modèle
MapReduce, c’est la spécialisation (choix 1) qui s’impose,
pour des raisons qui tiennent aux propriétés des méthodes
d’agrégation de données, pas toujours aussi simple que de
mélanger deux jus d’oranges.
◼ Dans une configuration avec plusieurs ateliers d’assemblage,
chacun est donc spécialisé pour traiter une ou plusieurs
catégories. Bien entendu, il faut s’assurer que chaque
catégorie est prise en charge par un atelier. C’est le rôle d’une
nouvelle machine, le répartiteur.
◼ Nous avons deux ateliers d’assemblage, le premier prenant en
charge les pommes et les oranges, et le second les ananas. 93

93

Jus de fruits MapReduce


◼ C’est fini ! Cette fois nous avons une métaphore
complète d’un processus MapReduce dans un
contexte Cloud/Big Data.
◼ Tirons une dernière leçon avant de le reformuler en
termes abstraits/informatiques.
◼ Leçon 7 : distribution vers les ateliers d’assemblage;
Si nous avons plusieurs ateliers d’assemblage, il
faut mettre en place une opération de répartition qui
envoie chaque type de fruit vers l’atelier spécialisé.
Cette opération doit garantir que chaque type de
fruit a son atelier. 94

94

47
Plan
◼ Introduction
◼ Modélisation Objet JSON
◼ Installation
◼ Présentation de MongoDB
◼ Requêtes MongoDB
◼ Le modèle MapReduce
◼ Découverte à l’aide d’un exemple
◼ Le modèle MapReduce en termes informatiques
◼ Frameworks MapReduce : MongoDB 95

◼ Conclusion
95

MapReduce
◼ Dans cette partie, nous caractériserons le modèle
MapReduce en termes informatiques.
◼ Pour l’instant, nous nous concentrons uniquement
sur la compréhension de ce que spécifie un
traitement MapReduce, et pas sur la manière dont
ce traitement est exécuté.
◼ Nous savons par ce qui précède qu’il est possible
de le paralléliser, mais il est également tout à fait
autorisé de l’exécuter sur une seule machine en
deux étapes. C’est le scénario que nous adoptons
pour l’instant. 96

96

48
Le modèle MapReduce
◼ Le principe de MapReduce est ancien et provient de la
programmation fonctionnelle. Il se résume ainsi :
➢ Etant donné une collection d’items, on applique à chaque
item un processus de transformation individuelle (phase
dite “de Map”) qui produit des valeurs intermédiaires
étiquetées.
➢ Ces valeurs intermédiaires sont regroupées par étiquette
et soumises à une fonction d’assemblage (on parlera plus
volontiers d’agrégation en informatique) appliquée à
chaque groupe (phase dite “de Reduce”).
◼ La phase de Map correspond à notre atelier de
transformation, la phase de Reduce à notre atelier
97
d’assemblage.
97

Notions du modèle MapReduce


◼ Un item d’entrée est une valeur quelconque
apte à être soumise à la fonction de
transformation.
◼ Dans tout ce qui suit, nos items d’entrée
seront des documents structurés.
◼ Dans notre exemple culinaire, les items
d’entrées sont les fruits “bruts” : pommes,
oranges, ananas, etc. La transformation
appliquée aux items est représentée par une
fonction de Map. 98

98

49
La fonction Map
◼ La fonction de Map, notée 𝐹𝑚𝑎𝑝 est appliquée
à chaque item de la collection, et produit zéro,
une ou plusieurs valeurs dites
“intermédiaires”, placées dans un
accumulateur.
◼ Dans notre exemple, 𝐹map est l’épluchage.
Pour un même fruit, on produit plusieurs
valeurs (les quartiers), voire aucune si le fruit
est pourri. L’accumulateur est le tas à droite
du cuisinier. 99

99

La fonction Map
◼ Il est souvent nécessaire de partitionner les valeurs
produites par le map en plusieurs groupes. Il suffit de
modifier la fonction 𝐹𝑚𝑎𝑝 pour qu’elle émette non plus
une valeur, mais associe chaque valeur au groupe auquel
elle appartient.
◼ 𝐹𝑚𝑎𝑝 produit, pour chaque item, une paire (k, v), où k est
l’identifiant du groupe et v la valeur à placer dans le
groupe. L’identifiant du groupe est déterminé à partir de
l’item traité. (c’est ce que nous avons informellement
appelé “étiquette” dans la présentation de l’exemple.)
◼ Dans le modèle MapReduce, on appelle paire
intermédiaire les données produites par la phase de Map. 100
100

50
La paire intermédiaire
◼ Une paire intermédiaire est produite par la fonction de
Map ; elle est de la forme (k, v) où k est l’identifiant (ou
clé) d’un groupe et v la valeur extraite de l’item d’entrée
par 𝐹𝑚𝑎𝑝.
◼ Pour notre exemple culinaire, il y a trois groupes, et donc
trois identifiants possibles : pomme, orange, ananas.
◼ À l’issue de la phase de Map, on dispose donc d’un
ensemble de paires intermédiaires. Chaque paire étant
caractérisée par l’identifiant d’un groupe, on peut
constituer les groupes par regroupement sur la valeur de
l’identifiant. On obtient des groupes intermédiaires. 101

101

Le groupe intermédiaire
◼ Un groupe intermédiaire est l’ensemble des
valeurs intermédiaires associées à une même
valeur de clé.
◼ Nous aurons donc le groupe des quartiers de
pomme, le groupe des quartiers d’orange, et le
groupe des rondelles d’ananas.
◼ On entre alors dans la seconde phase, dite de
Reduce.
◼ La transformation appliquée à chaque groupe est
102
définie par la fonction de Reduce.
102

51
La fonction de Reduce
◼ Dans la seconde phase, la fonction de transformation dite de
Reduce, notée 𝐹𝑟ed, est appliquée à chaque groupe
intermédiaire et produit une valeur finale. L’ensemble des
valeurs finales (une pour chaque groupe) constitue le résultat
du traitement MapReduce.

103

103

Résumé du modèle MapReduce


◼ On part d’une collection de documents 𝑑1, 𝑑2, ・ ・ ・ , 𝑑𝑛.
La fonction 𝐹𝑚𝑎𝑝 produit des paires intermédiaires sous la
forme de documents 𝑑𝑗𝑖 , dont l’identifiant (𝑗) désigne le
groupe d’appartenance.
◼ Notez les doubles flèches : un document en entrée peut
engendrer plusieurs documents en sortie du map. 𝐹𝑚𝑎𝑝 place
chaque 𝑑𝑗𝑖 dans un groupe 𝐺𝑗 , 𝑗 ∈ [1, 𝑘].
◼ Quand la phase de map est terminée (et pas avant !), on peut
passer à la phase de reduce qui applique successivement 𝐹𝑟𝑒𝑑
aux documents de chaque groupe.
◼ On obtient, pour chaque groupe, une valeur (un document de
manière générale) 𝑣𝑗 . 104

104

52
Résumé du modèle MapReduce
◼ En complément, notons que ce mécanisme a quelques propriétés
intéressantes :
➢ il est générique et s’applique à de nombreux problèmes,
➢ il se parallélise très facilement ;
➢ il est assez tolérant aux pannes dans une contexte distribué.
◼ Pour les 2 derniers aspects, il est important que chaque document
soit traité indépendamment du contexte. Concrètement,
l’application de 𝐹𝑚𝑎𝑝 à un document d doit donner un résultat qui
ne dépend ni de la position de d dans la collection, ni de ce qui s’est
passé avant ou après dans la chaîne de traitement, ni de la machine
ou du système, etc. En pratique, cela signifie que la fonction 𝐹𝑚𝑎𝑝
ne conserve pas un état qui pourrait varier et influer sur le résultat
105
produit quand elle est appliquée à d.

105

Plan
◼ Introduction
◼ Modélisation Objet JSON
◼ Installation
◼ Présentation de MongoDB
◼ Requêtes MongoDB
◼ Le modèle MapReduce
◼ Frameworks MapReduce : MongoDB
◼ Conclusion 106

106

53
Frameworks MapReduce : MongoDB
◼ MongoDB dispose d’un moteur de calcul
MapReduce qui est relativement facile à
expérimenter.
◼ Les fonctions de Map et de Reduce sont codées en
javascript, et il est possible de les tester localement
sans recourir à une grappe de serveurs et à du Big
Data.
◼ Nous donnons ici les fonctions complètes et le mode
d’emploi : avec un peu d’agilité vous pouvez
copier/coller les exemples et les modifier pour vos
107
tests.
107

Frameworks MapReduce : MongoDB


◼ La programmation d’un traitement MapReduce requiert
l’utilisation d’un environnement de programmation
spécialisé (ou framework).
◼ Dans un framework MapReduce, tout ce qui est générique
est pris en charge, et notamment toute l’organisation et la
gestion de la répartition des traitements, quand on est
dans un contexte distribué.
◼ De fait, avec un tel environnement, le programmeur se
contente de définir la partie purement fonctionnelle du
traitement : la fonction de Map, 𝐹𝑚𝑎𝑝, et la fonction de
Reduce, 𝐹𝑟𝑒𝑑. 108

108

54
Frameworks MapReduce : MongoDB
◼ Un traitement MapReduce repose sur la notion de
fonction de second ordre. Cela signifie
simplement que l’environnement (framework)
fournit deux fonctions, map() et reduce(), qui
prennent chacune en entrée, respectivement, les
fonctions 𝐹𝑚𝑎𝑝 et 𝐹𝑟𝑒𝑑 mentionnées ci-dessus.
◼ Ce sont des fonctions qui prennent en argument
d’autres fonctions et les appliquent aux données,
d’où la notion de “second-ordre”.
109

109

Premier traitement MapReduce/MongoDB

◼ Nous allons produire un document par réalisateur,


avec la liste des films qu’il/elle a réalisé.
◼ Conceptuellement, nous créons un groupe par
réalisateur, plaçons dans ce groupe les films
pendant la phase de map et construisons le
document final dans la phase de reduce.
◼ La spécification consiste à définir les deux
fonctions à appliquer (𝐹𝑚𝑎𝑝 et 𝐹𝑟𝑒𝑑).

110

110

55
Premier traitement MapReduce/MongoDB

◼ Voici la fonction de map :


◼ var mapRealisateur = function() {
emit(this.director._id, this.title);
};
◼ En javascript, les fonctions peuvent se stocker dans des
variables. L’instruction emit produit une paire (clé,
valeur), constituée ici de l’identifiant du réalisateur, et du
titre du film.
◼ Notez que la fonction ne prend aucun argument :
implicitement, elle dispose comme contexte du document
auquel elle s’applique, désigné par this. 111

111

Premier traitement MapReduce/MongoDB

◼ Voici la fonction de reduce.


◼ var reduceRealisateur = function(directorId, titres) {
var res = new Object();
res.director = directorId;
res.films = titres;
return res;
};
◼ Une fonction de reduce prend deux arguments : l’identifiant du
groupe auquel elle s’applique (ici, directorId) et la liste (un
tableau en javascript) des valeurs produites par le map.
◼ Dans notre exemple, nous construisons la valeur de résultat
comme un objet res auquel on affecte deux propriétés 112:
directorId et titres.
112

56
Premier traitement MapReduce/MongoDB

◼ Il ne reste plus qu’à lancer un traitement,


avec la fonction mapReduce sur la collection
movies. Voici la syntaxe.
➢ db.movies.mapReduce(mapRealisateur,
reduceRealisateur, {out: {"inline": 1}} )
◼ Le premier paramètre est la fonction de map,
le second la fonction de reduce, et le
troisième indique la sortie, ici l’écran.
113

113

Premier traitement MapReduce/MongoDB

◼ En exécutant ce code, vous devriez obtenir, pour chaque groupe, un


résultat de la forme suivante.
◼ {
"_id" : "artist:111",
"value" : {
"director" : "artist:111",
"films" : [
"Jeanne d'Arc",
"Le cinquième élément",
"Nikita",
"Léon",
"Le grand bleu"
] 114
}
114

57
Premier traitement MapReduce/MongoDB

◼ MongoDB propose plusieurs options pour l’exécution


d’un traitement MapReduce.
◼ La plus utile (et la plus générale, présente dans tous
les systèmes) consiste à prendre en entrée non pas une
collection entière, mais le résultat d’une requête. On
passe pour cela un objet query dans le document-
paramètre en troisième position. Voici un exemple.
➢ db.movies.mapReduce(mapRealisateur,
reduceRealisateur, {out: {"inline": 1}, query:
{"country": "USA"}} )
115

115

Premier traitement MapReduce/MongoDB

◼ Une autre possibilité intéressante est le calcul


incrémental d’un traitement MapReduce.
◼ En bref, on peut stocker le résultat dans une
nouvelle collection, et mettre à jour cette
collection, sans avoir à tout recalculer, quand de
nouveaux documents apparaissent dans la
collection en entrée.
◼ Il s’agit d’une spécificité MongoDB, dont nous
n’allons pas insister dessus : reportez-vous à la
documentation. 116

116

58
Plan
◼ Introduction
◼ Modélisation Objet JSON
◼ Installation
◼ Présentation de MongoDB
◼ Requêtes MongoDB
◼ Le modèle MapReduce
◼ Frameworks MapReduce : MongoDB
◼ Conclusion 117

117

Conclusion
◼ Ce cours portait sur l'utilisation de
MongoDB.
◼ Les bases de données NoSQL,
notamment MongoDB, sont très utilisées
de nos jours.
◼ Il est donc très important de se
familiariser avec au moins l'une d'elles.
118

118

59

Vous aimerez peut-être aussi