Module 5 (Section 2) : Introduction à MongoDB
Riadh ZAAFRANI Décembre 2020
1ère année MP2L
1
1
Plan
◼Introduction ◼Installation ◼Client Mongo ◼Requêtes MongoDB ◼Le modèle MapReduce ◼Frameworks MapReduce : MongoDB ◼Conclusion 2
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.
il
◼ De plus,
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
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 hautes qui performances, une haute disponibilité, et mise à l'échelle automatique.
documents
fournit
de
4
4
2
Introduction
◼ Un enregistrement dans MongoDB est un document,
qui est une structure de données champ-valeur.
◼ Les documents dans MongoDB sont similaires à des objets JSON. 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”]
}
5
5
Plan ◼Introduction ◼Installation ◼Client Mongo ◼Requêtes MongoDB ◼Le modèle MapReduce ◼Frameworks MapReduce : MongoDB ◼Conclusion
6
6
3
Installation
◼ MongoDB est un système libre de droits (pour sa version de
base), téléchargeable à :
◼ https://www.mongodb.com/download-
center/community?jmp=docs
à
la dernière ◼ Télécharger stable version correspondant votre système d’exploitation et ensuite décompressez l’archive ou bien suivez les étapes d'installation :
récupérée
7
7
Installation sous Windows
◼ MongoDB fonctionne sur plusieurs plates-formes, que ce soit en architecture 32-bits comme en architecture 64-bits.
◼ On peut obtenir la version de Windows utilisée en ouvrant l'invite de commande et en tapant les deux commandes suivantes :
➢ wmic os get caption ➢ wmic os get osarchitecture ◼ La première nous donne la version de Windows la seconde nous
(Windows 7, Windows 8…) et donne l'architecture (32-bits, 64-bits).
8
8
4
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\4.2. Vous devriez ajouter C:\Program Files\MongoDB\Server\4.2\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\4.2\data\.
9
9
Configuration de l'environnement MongoDB
lancer
◼ MongoDB fonctionne en mode classique client/serveur. la le serveur, exécutez Pour commande mongod qui se trouve dans bin, et c’est tout. ◼ Vous pouvez spécifier un autre chemin pour les fichiers de données en utilisant l'option --dbpath à mongod.exe, par exemple :
simplement
➢ mongod --dbpath "C:\test\mongodb\data”
10
10
5
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 processus indique mongod.exe a bien été exécuté.
27017
que
qui
le
◼ 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.
11
11
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, sont
choix recommandables une application Web d’administration de MongoDB à peu près équivalente à phpMyAdmin, et RoboMongo, plus facile d’installation.
RockMongo,
deux
12
12
6
Le client RoboMongo
◼ RoboMongo
est
un graphique toutes à
client disponible pour les robomongo.org.
plate-formes
à
◼ C’est sans doute le privilégier. choix est très l’installation simple, l’outil semble assez complet et en évolution rapide.
Le client RoboMongo
13
14
13
14
7
Plan ◼Introduction ◼Installation ◼Client Mongo ◼Requêtes MongoDB ◼Le modèle MapReduce ◼Frameworks MapReduce : MongoDB ◼Conclusion
15
15
Le client Mongo
◼ Pour se connecter à MongoDB, en utilisant l’interpréteur de commande, ouvrez une autre fenêtre d'invite de commandes et l’arrêter, appuyez sur Control + C dans le terminal où l'instance est lancée.
tapez la commande mongo. Pour
◼ L’interpréteur de commande se lance comme suit : ◼ C:\mongo
MongoDB shell version: 3.2.10 connecting to: test >
16
16
8
Le client Mongo
◼ La connexion ne peut réussir que si le service
MongoDB est lancé.
◼ Par défaut, mongo recherche un serveur de le port 27017 sur
base de données sur l'interface locale.
◼ Pour se connecter à un serveur sur un port ou
une interface différente, utilisez les paramètres --port et --host.
17
17
Le client Mongo
◼Après le lancement de mongo, votre session va utiliser par défaut la base de données « test ».
◼L’outil mongo 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.
18
18
9
Le client Mongo
◼ 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.
19
19
Création d'une collection et insertion de documents
◼ Une base est 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.insert ({"nom": "1Master info"}) ◼ Il existe donc un objet (javascript) implicite, db, auquel on
soumet des demandes d’exécution de certaines méthodes.
20
20
10
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 : ObjectId("5de2282d319c52285f46d661"), JSON) "nom" : "1Master info" }
"_id"
{
◼ MongoDB associe un identifiant unique à chaque document, de nom conventionnel _id, et lui attribue une valeur si elle n’est pas indiquée explicitement.
21
21
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, la structure) vers l’application.
tests sur
22
22
11
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.count() ◼ Et finalement, on peut supprimer une collection : ➢ db.groupes.drop()
23
Publicité
23
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 :
téléchargeable
à
films http://webscope.bdpedia.fr/
complets
24
24
12
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"} ] }
25
25
Création de la base
◼ Comme il serait fastidieux de les insérer un par un, nous l’utilitaire allons d’import Il prend en entrée un tableau JSON contenant la liste des objets à insérer.
utiliser de MongoDB.
◼ Dans notre cas, nous allons l’export JSON de la le
utiliser base Webscope format est le suivant.
dont
[ { "_id": "movie:1", "title": "Vertigo", "year": "1958", "director": { "_id": "artist:3", "last_name": "Hitchcock", "first_name": "Alfred", "birth_date": "1899 » }, "actors": [ { "_id": "artist:15", "first_name": "James", "last_name": "Stewart", }, {"_id": "artist:16", "first_name": "Kim", "last_name": "Novak",} ] }, {"_id": "movie:2", "title": "Alien", …} ]
26
26
13
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 des commandes :
l’interpréteur
directement
partir
de
à
◼ mongoimport -d test -c movies --file movies.json --jsonArray
◼ Ne pas oublier l’argument jsonArray qui s’agit
à d’un d’import individuellement, et pas d’un unique document JSON.
indique à l’utilitaire créer d’objets
tableau
qu’il
27
27
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 movies-refs --file moviesRefs.json --jsonArray
28
28
14
Plan
◼Introduction ◼Installation ◼Client Mongo ◼Requêtes MongoDB ◼Le modèle MapReduce ◼Frameworks MapReduce : MongoDB ◼Conclusion 29
29
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.
30
30
15
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 (le une collection en donnant un objet “motif/pattern”, en JSON) dont chaque attribut est interprété comme une contrainte sur la structure des objets à rechercher.
31
31
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 suivants, il me suffit de taper it.
les documents
32
32
16
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.count()
33
33
Sélections
◼ Comme en SQL (étendu), les options skip et limit le résultat. La requête permettent de “paginer” 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).
34
34
17
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).
35
35
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
les documents au fur et à mesure qu’il les trouve.
le système peut délivrer
tri,
36
36
18
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 de programmation.
37
37
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 ?
38
38
19
Critères de recherche
◼ On utilise dans ce cas des chemins, un peu à la XPath, mais avec une syntaxe plus “orienté-objet”.
◼ Voici comment on recherche les films de David Fincher.
➢ db.movies.find
({"director.last_name": "Fincher"})
39
{ "_id" : "movie:14", "title" : "Seven", "year" : 1995, "genre" : "crime", "summary" : "A New York, un criminel anonyme a décidé de commettre 7 meurtres basés.... ",
"country" : "USA", "director" : {
"_id" : "artist:31", "last_name" : "Fincher", "first_name" : "David", "birth_date" : "1962" },
"actors" : [ {
"_id" : "artist:18", "first_name" : "Kevin",
"last_name" : "Spacey", "birth_date" : "1959", "role" : "Doe"
◼
}…. ]}
39
Critères de recherche
◼ Et pour les acteurs, qui sont eux-mêmes dans un tableau ? Ca fonctionne de la même manière.
➢ db.movies.find
({"actors.last_name": "Spacey"})
◼ La requête s’interprète donc comme : “Tous les films dont l’un des acteurs se nomme Spacey”. ◼
{ "_id" : "movie:14", "title" : "Seven", "year" : 1995, "genre" : "crime", "summary" : "A New York, un criminel anonyme a décidé de commettre 7 meurtres basés.... ",
"country" : "USA", "director" : {
"_id" : "artist:31", "last_name" : "Fincher", "first_name" : "David", "birth_date" : "1962" },
"actors" : [ {
"_id" : "artist:18", "first_name" : "Kevin",
"last_name" : "Spacey", "birth_date" : "1959", "role" : "Doe"
}…. ]}
40
40
20
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 41 frappe sur des noms d’attributs.
41
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": null, "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és 42 ($gt, $gte, $lt, $lte, $ne).
42
21
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": 'j'} )
◼ Le second argument est un objet JSON dont les attributs sont ceux à conserver dans le résultat.
43
Publicité
43
Projections
◼ La valeur des attributs dans cet objet-projection ne prend que deux interprétations : Toute valeur autre que 0 ou null indique que l’attribut doit être conservé. Si on choisit au contraire d’indiquer les attributs à exclure, on leur donne la valeur 0 ou null.
◼ 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": null, "summary": 0})
44
44
22
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})
45
45
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"]}})
46
46
23
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"]}})
47
47
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})
48
48
24
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.
49
49
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"} ] } )
50
50
25
Jointures
◼ Grosso modo,
◼ Voici pour l’essentiel en ce qui concerne les recherches portant sur une collection et consistant à sélectionner des documents. on
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.
obtient
◼ Avec Mongo, il faut bricoler.
51
51
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.
est
cohérente
◼ C’est une limitation très importante du point de vue de la gestion de données. On peut considérer qu’elle 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 lui-même.
avec
une
52
52
26
Jointures
imaginer
◼ Cela étant, on peut
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 :
53
53
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 la
en Javascript, nous pouvons en fait méthode assez simplement.
illustrer
◼ Considérons la requête : “Donnez tous les films
dont le directeur est Clint Eastwood”.
54
54
27
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"})
55
55
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}) le
◼ Voilà
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
56
56
28
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); }
57
57
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 les
le serveur si ce dernier
implantait
par 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.
58
58
29
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.
59
59
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...
60
60
30
Plan
◼Introduction ◼Installation ◼Client Mongo ◼Requêtes MongoDB ◼Le modèle MapReduce
◼ Découverte à l’aide d’un exemple ◼ Le modèle MapReduce en termes informatiques
◼Frameworks MapReduce : MongoDB ◼Conclusion
61
61
MapReduce
◼Nous
plus
complet
abordons
maintenant
un processus le traitement d’une collection, que nous allons appeler chaîne de traitement par traduction processing pipelines”.
“data
pour
de
62
62
31
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.
63
63
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.
Publicité
◼ 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.
64
64
32
Plan
◼Introduction ◼Installation ◼Client Mongo ◼Requêtes MongoDB ◼Le modèle MapReduce
◼ Découverte à l’aide d’un exemple ◼ Le modèle MapReduce en termes informatiques
◼Frameworks MapReduce : MongoDB ◼Conclusion
65
65
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 ; toutes les pommes dans un ◼ Le pressage : on met
pressoir, et on récupère le jus.
66
66
33
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 il produit du jus de
un tas de pommes épluchées et pomme.
67
67
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 produits
transformation
une
aux
contraire, regroupés : ici, des tas de pommes.
applique
◼ Leçon 2 : l’atelier d’assemblage est centré sur les tas de pommes. Dans l’atelier d’assemblage, on applique des 68 transformations à des ensembles de pommes.
68
34
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. une
devient
phase
◼ La
phase
d’épluchage d’épluchage/découpage.
69
69
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.)
70
70
35
Beaucoup de jus de pomme
◼ Nous avons ainsi notre premier processus identifié ses
MapReduce, et nous avons 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.
71
71
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 les
répartissez équitablement
affectez c pressoirs et quartiers dans chacun.
◼ Petit inconvénient : vous obtenez plusieurs fûts de jus de pomme, un par pressoir, avec une qualité éventuellement 72 variable. Ce n’est sans doute pas très grave.
72
36
Beaucoup de jus de pomme
l’atelier
◼ Dans
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 au nombre de cuisiniers.
73
73
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 (avec le matériel correspondant) jour, 10 cuisiniers 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 et est parallélisable proportionnelle aux ressources (humaines et matérielles) affectées.
jus de pomme
74
74
37
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.
75
75
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.
76
76
38
Jus de fruits MapReduce
◼ En revanche, pendant la première phase, on peut soumettre un tas indifférencé 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.).
77
77
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 l’atelier d’assemblage robuste. Les produits fournis par 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 groupe entrée, 78 d’appartenance.
indiquant
produit
en
le
/
78
39
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.
79
79
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 s’assurer que chaque il catégories. Bien entendu, catégorie est prise en charge par un atelier. C’est le rôle d’une nouvelle machine, le répartiteur.
faut
◼ Nous avons deux ateliers d’assemblage, le premier prenant en charge les pommes et les oranges, et le second les ananas.
80
80
40
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; il Si nous avons plusieurs ateliers d’assemblage, 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.
81
81
82
Plan
◼Introduction ◼Installation ◼Client Mongo ◼Requêtes MongoDB ◼Le modèle MapReduce
◼ Découverte à l’aide d’un exemple ◼ Le modèle MapReduce en termes informatiques
◼Frameworks MapReduce : MongoDB ◼Conclusion
82
41
MapReduce
◼ Dans cette partie, nous caractériserons le modèle
MapReduce en termes informatiques.
◼ Pour l’instant, nous nous concentrons uniquement la compréhension de ce que spécifie un sur 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.
83
83
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 la phase de Reduce à notre atelier
84
transformation, d’assemblage.
84
42
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