Académique Documents
Professionnel Documents
Culture Documents
Note
Le chemin vers l’exécutable mongoimport est nécessaire, ou la variable
d’environnement PATH contenant le chemin vers mongo/bin. L’opération peut prendre
quelques secondes (118000 items à insérer)
Dans la console mongo vérifier que les données ont été insérées : db.publis.count();
Interrogation simple
Exprimez des requêtes simples (pas de MapReduce) pour les recherches suivantes :
1. Liste de tous les livres (type « Book ») ;
2. Liste des publications depuis 2011 ;
3. Liste des livres depuis 2014 ;
4. Liste des publications de l’auteur « Toru Ishida » ;
5. Liste de tous les éditeurs (type « publisher »), distincts ;
6. Liste de tous les auteurs distincts ;
7. Trier les publications de « Toru Ishida » par titre de livre et par page de début ;
8. Projeter le résultat sur le titre de la publication, et les pages ;
9. Compter le nombre de ses publications ;
10. Compter le nombre de publications depuis 2011 et par type ;
11. Compter le nombre de publications par auteur et trier le résultat par ordre.
Page 3 sur 10
Pratique de Map/Reduce
Commandes pour retrouver l’environnement de travail complet
Sur les machines du CNAM, le serveur mongod tourne déjà : en ouvrant une console puis en
saisissant successivement les commandes ci-dessous, vous devriez retrouver un robo3T
fonctionnel.
wget http://b3d.bdpedia.fr/files/dblp.json.zip
unzip dblp.json.zip
mongoimport -d dblp -c publis --file dblp.json --jsonArray
wget https://download.robomongo.org/1.2.1/linux/robo3t-1.2.1-linux-x86_64-3e50a65.tar.gz
tar -xvzf robo3t-1.2.1-linux-x86_64-3e50a65.tar.gz
cd robo3t-1.2.1-linux-x86_64-3e50a65/bin/
./robo3t
Sur une machine personnelle, il sera peut-être nécessaire de lancer le serveur MongoDB et
de modifier éventuellement les paramètres du mongoimport.
Quelques rappels
Pour exprimer une requête MapReduce, il faut définir une fonction de map, une fonction
de reduce, un filtre (optionnel), lancer le tout avec l’opérateur mapReduce et consulter le
résultat (optionnel !). Soit:
map var mapFunction = function () {emit(this.year, 1);};
Mappez et réducez
Pour les recherches suivantes, donnez la requête MapReduce sur la base en changeant la
requête Map et/ou Reduce
1. Pour chaque document de type livre, émettre le document avec pour clé « title »
2. Pour chacun de ces livres, donner le nombre de ses auteurs
3. Pour chaque livre publié par Springer et composé de chapitres (ayant
l’attribut « booktitle »), donner le nombre des chapitres.
Page 4 sur 10
Attention
La fonction de reduce n’est évaluée que lorsqu’il y a au moins 2 documents pour une même
clé. Il est donc nécessaire d’appliquer un filtre après génération du résultat.
4. Pour l’éditeur « Springer », donner le nombre de publications par année
5. Pour chaque couple « publisher & année » (il faut que publisher soit présent),
donner le nombre de publications.
Important
la clé du emit() doit être un document.
6. Pour l’auteur « Toru Ishida », donner le nombre de publications par année
7. Pour l’auteur « Toru Ishida », donner le nombre moyen de pages pour ses
articles (type Article)
8. Pour chaque auteur, lister les titres de ses publications
Attention
La sortie du map et du reduce doit être un document (pas un tableau)
9. Pour chaque auteur, lister le nombre de publications associé à chaque année
10. Pour l’éditeur « Springer », donner le nombre d’auteurs par année
11. Compter les publications de plus de 3 auteurs
12. Pour chaque éditeur, donner le nombre moyen de pages par publication
13. Pour chaque auteur, donner le minimum et le maximum des années avec des
publications, ainsi que le nombre total de publications
Page 5 sur 10
Correction
1. var mapFunction = function () {
2. if (this.type == "Book")
3. emit(this.title, this);
4. };
5.
6. var reduceFunction = function (key, values) {
7. return {articles : values};
8. };
9.
10. var queryParam = {query:{}, out:"result_set"};
11. ou
12. var mapFunction = function () {emit(this.title, this);};
13.
14. var reduceFunction = function (key, values) {
15. return {articles : values};
16. };
17.
18. var queryParam = {query:{type : "Book"}, out:"result_set"};
Note
Peut être plus efficace si un index est présent sur le type
19. var mapFunction = function () {
20. if(this.type == "Book")
21. emit(this.title, this.authors.length);
22. };
23.
24. var reduceFunction = function (key, values) {
25. return {articles : values};
26. };
27.
28. var queryParam = {query:{}, out:"result_set"};
29.
30. var mapFunction = function () {
31. if(this.publisher=="Springer" && this.booktitle)
32. emit(this.booktitle, 1);
33. };
Page 6 sur 10
34.
35. var reduceFunction = function (key, values) {
36. return Array.sum(values);
37. };
38.
39. var queryParam = {query:{}, out:"result_set"};
40.
41. db.publis.mapReduce(mapFunction,
42. reduceFunction, queryParam);
43.
44. db.result_set.find({value:{$gte:2}});
45.
46. var mapFunction = function () {
47. if(this.publisher == "Springer")emit(this.year, 1);
48. };
49.
50. var reduceFunction = function (key, values) {
51. return Array.sum(values);
52. };
53.
54. var mapFunction = function () {
55. if(this.publisher)
56. emit({publisher:this.publisher, year:this.year}, 1);
57. };
58.
59. var reduceFunction = function (key, values) {
60. return Array.sum(values);
61. };
62.
63. var mapFunction = function () {
64. if(Array.contains(this.authors, "Toru Ishida"))
65. emit(this.year, 1);
66. };
67.
68. var reduceFunction = function (key, values) {
69. return Array.sum(values);
70. };
Page 7 sur 10
71.
72. var queryParam = {query:{}, out:"result_set"};
73.
74. ou
75.
76. .. code-block:: javascript
77.
78. var mapFunction = function () {emit(this.year, 1);};
79.
80. var reduceFunction = function (key, values) {
81. return Array.sum(values);
82. };
83.
84. var queryParam = {
85. query:{authors:"Toru Ishida"}, out:"result_set"};
86.
87. var mapFunction = function () {
88. emit(null, this.pages.end - this.pages.start);
89. };
90.
91. var reduceFunction = function (key, values) {
92. return Array.avg(values);
93. };
94.
95. var queryParam = {query:{authors:"Toru Ishida"}, out:"result_set"};
96.
97. var mapFunction = function () {
98. for(var i=0;i<this.authors.length;i++)
99. emit(this.authors[i], this.title);};
100.
101. var reduceFunction = function (key, values) {
102. return {titles : values};
103. };
104.
105. var mapFunction = function () {
106. for(var i=0;i<this.authors.length;i++)
107. emit({author : this.authors[i], year : this.year}, 1);};
Page 8 sur 10
108.
109. var reduceFunction = function (key, values) {
110. return Array.sum(values);
111. };
112.
113. var mapFunction = function () {
114. for(var i=0;i<this.authors.length;i++)
115. emit(this.year, this.authors[i]);};
116.
117. var reduceFunction = function (key, values) {
118. var distinct = 0;var authors = new Array();
119.
120. for(var i=0;i<values.length;i++)
121. if(!Array.contains(authors, values[i]))
122. {
123. distinct++;
124. authors[authors.length] = values[i];
125. }
126.
127. return distinct;};
128.
129. var mapFunction = function () {
130. if(this.authors.length >3)emit(null, 1);
131. };
132.
133. var reduceFunction = function (key, values) {
134. return Array.sum(values);
135. };
136.
137. var mapFunction = function () {
138. if(this.pages && this.pages.end)
139. emit(this.publisher, this.pages.end - this.pages.start);
140. };
141.
142. var reduceFunction = function (key, values) {
143. return Array.avg(values);
144. };
Page 9 sur 10
145.
146. var queryParam = {query:{}, out:"result_set"};
147.
148. var mapFunction = function () {
149. for(var i=0;i<this.authors.length;i++)
150. emit(this.authors[i], {min : this.year,
151. max : this.year, number : 1});};
152.
153. var reduceFunction = function (key, values) {
154.
155. var v_min = 1000000;var v_max = 0;var v_number = 0;
156.
157. for(var i=0;i<values.length;i++){
158. if(values[i].min < v_min)v_min = values[i].min;
159. if(values[i].max > v_max)v_max = values[i].max;
160. v_number++;
161. }
162. return {min:v_min, max:v_max, number:v_number};
163. };
164.
Pour les mises à jour suivantes, vérifier le contenu des données avant et après la mise à
jour.
1. Mettre à jour tous les livres contenant « database » en ajoutant l’attribut
« Genre » : « Database »
2. Supprimer le champ « number » de tous articles
3. Supprimer tous les articles n’ayant aucun auteur
4. Modifier toutes les publications ayant des pages pour ajouter le champ « pp »
avec pour valeur le motif suivant : pages.start--pages.end
Indexation 2Dsphere
Nous pouvons indexer les données avec 2DSphere qui permet de faire des recherches en
2 dimensions.
Pour ce faire, télécharger le fichier cities15000.csv.zip. Décompressez-le. Créer une
collection cities dans la base de données, et importer les données à l’aide d’un programme
de lecture CSV (à vous de le créer). Le schéma de sortie doit contenir pour les coordonnées
les informations suivantes :
"coordinate" : [XXXXX, YYYYY]
L’attribut coordinate sera alors indexé :
db.publis.ensureIndex( { coordinate : "2d" } );
Pour interroger l’index, il faut utiliser un opérateur 2D et l’utiliser sur coordinate