Tp 2 Maitriser MongoDB
MongoDB
MongoDB est une base de données NoSQL distribué de type Document Store.
Gérer de gros volumes
Facilité de déploiement et d’utilisation
Possibilité de faire des choses complexes tout de même
Modèle des données
Principe de base : les données sont des documents
stocké en Binary JSON (BSON)
documents similaires rassemblés dans des collections
pas de schéma des documents définis en amont
o contrairement à un BD relationnel ou NoSQL de type Column Store
les documents peuvent n’avoir aucun point commun entre eux
un document contient (généralement) l’ensemble des informations
o pas (ou très peu) de jointure à faire
BD respectant CP (dans le théorème CAP)
o propriétés ACID au niveau d’un document
Point sur JSON
JavaScript Object Notation
Créé en 2005
On parle de littéral
Format d’échange de données structurées léger
Schéma des données non connu
o contenu dans les données
Basé sur deux notions :
o collection de couples clé/valeur
o liste de valeurs ordonnées
Structures possibles :
1
o objet (couples clé/valeur) :
o {}
o { "nom": "jollois", "prenom": "fx" }
o tableau (collection de valeurs) :
o []
o [ 1, 5, 10]
o une valeur dans un objet ou dans un tableau peut être elle-même un littéral
Deux types atomiques (string et number) et trois constantes (true, false, null)
Compléments
BSON : extension de JSON
Quelques types supplémentaires (identifiant spécifique, binaire, date, …)
Distinction entier et réel
Schéma dynamique
Documents variant très fortement entre eux, même dans une même collection
On parle de self-describing documents
Ajout très facile d’un nouvel élément pour un document, même si cet élément est
inexistant pour les autres
Pas de ALTER TABLE ou de redesign de la base
Pas de jointures entre les collections
Langage d’interrogation
Pas de SQL (bien évidemment), ni de langage proche
Définition d’un langage propre (basé sur JS)
Langage permettant plus que les accès aux données
o définition de variables
o boucles
Accès à MongoDB
Pour lancer le shell de Mongo, il suffit d’exécuter la commande suivante dans le terminal
de commande.
2
mongo
Une fois connecté au shell, il est possible de connaître l’ensemble des bases de données
présentes sur le serveur. On utiliser la commande show dbs comme ci-dessous.
show dbs
Pour choisir la base sur laquelle on veut travailler, il faut la sélectionner à l’aide de la
commande use db (db étant à remplacé par le nom de la base de données choisie).
use Petshop
Une base de données est constituée d’une ou plusieurs collections. Chacune de celles-ci
contient un ensemble de documents. Pour lister celles-ci, on utilise la commande show
collections.
show collections
Créer la collection mammals
use Petshop
[Link]('mammals')
Insérer des documents dans la collection mammals
[Link]({name: "Polar Bear", species: " Bear " })
[Link]({name: "Star Nosed Mole", species: " cat" })
[Link]({name: "Star Nosed Mole", species: "dog" })
Dans MongoDB, on utilise un formalisme de type [Link]() :
db représente la base de données choisie grâce à la commande use (ce mot clé est
non modifiable)
collection représente la collection dans laquelle on va effectuer l’opération, et
doit donc correspondre à une des collections présentes dans la base
fonction() détermine l’opération à effectuer sur la collection.
3
En premier lieu, on peut dénombrer le nombre de documents de chaque collection, grâce
à la fonction count().
[Link]()
Les documents présents dans une collection n’ont pas de schémas prédéfinis. Si nous
souhaitons avoir une idée de ce que contient la collection, il est possible d’afficher un
document (le premier trouvé), avec findOne(). Cette opération permet de comprendre la
structure global d’un document, même s’il peut y avoir des différences entre documents.
[Link]()
Une autre fonction très utile pour mieux appréhender les données est de lister les valeurs
prises par les différents items de la collection, grâce à distinct(). Pour spécifier un sous-
item d’un item, il est nécessaire d’utiliser le formalisme [Link].
[Link]("name")
Recherche d’informations
Pour faire des recherches, il existe la fonction find(). Sans paramètre, elle renvoie
l’ensemble des documents. Il faut donc l’utiliser avec précautions. Mais celle-ci peut aussi
prendre deux paramètres :
les critères de sélection des documents
les choix d’items des documents à afficher
Ces deux paramètres doivent être écrits sous la forme d’objets JSON.
Dans ce premier exemple, on cherche le (ou les) animaux s’appelant " Polar Bear ".
[Link]({"name" : "Polar Bear"})
L’affichage rendu par find() est compact et peu lisible directement. On peut aérer ce
rendu en ajoutant la fonction pretty() pour avoir une présentation propre.
[Link]({"name" : "Polar Bear"}).pretty()
4
Si l’on désire n’afficher que certains éléments, il est possible d’ajouter un deuxième
argument spécifiant les items que l’on veut (avec 1) ou qu’on ne veut pas (avec 0).
[Link] ({"name" : "Polar Bear"},{ "name": 1 })
Par défaut, l’identifiant du document, toujours nommé _id, est renvoyé. Pour ne pas
l’avoir, il faut ainsi le préciser avec "_id": 0.
[Link] ({"name" : "Polar Bear"},{ "_id": 0, "name": 1 })
On peut utiliser l’expression régulière comme suit
[Link]({
name: /Nosed/
})
Exercice
1. Créer une nouvelle collection pets dans la base Petshop
2. Insérer les documents suivants dans la collection
[Link]({name: "Mikey", species: "Gerbil"})
[Link]({name: "Davey Bungooligan", species: "Piranha"})
[Link]({name: "Suzy B", species: "Cat"})
[Link]({name: "Mikey", species: "Hotdog"})
[Link]({name: "Terrence", species: "Sausagedog"})
[Link]({name: "Philomena Jones", species: "Cat"})
[Link]({name: "Mikey", species: "Cat"})
[Link]({name: "Mike", species: "Gerbil"})
3. Ajouter un autre Piranha et un rat appelé Henry
4. Utiliser find() pour afficher tous les animaux de compagnie.
5. Trouvez l'ID de Mikey le Gerbil.
6. Utiliser find() pour trouver Mikey par identifiant
exemple :[Link](ObjectId("557afc91c0b20703009f7edf"))
5
7. Utiliser find() pour trouver toutes les Gerbil.
8. Trouvez tous les animaux nommées Mikey.
9. Trouvez tous les animaux nommées Mikey qui sont des Gerbil.
10. Trouvez tous les animaux dont l’espèce contient la chaine de caractère
"dog".
A présent on va créer une autre collection nommé people
Insérer le document suivant
[Link]({name: "dave", age: 69, email: "davey@[Link]"})
- Ajouter une autre personne dont le nom est 'Yolanda Sasquatch'
- Ajouter 6 autres documents
On peut rechercher toutes les personnes dont l’âge est inférieur à 65 comme suit :
[Link]({
age: {
$gt: 65
}
})
})
On utilise
- $gt - Greater than (supérieur à)
- $gte (greater than or equal)
- $lt - Less than (inférieur à)
- $lte (less than or equal)
- $eq(equal)
- $ne (not equal)
- $in (présent dans la liste)
- $nin (non présent dans la liste)
- $exists – si le champ existe
-
6
Exercice
Copier le code javascript suivant dans le terminal Mongo. Il permet de créer une
collection de personnes. Certaines personnes ont un chat et d’autre pas.
use people
(function() {
var names = [
'Yolanda',
'Iska',
'Malone',
'Frank',
'Foxton',
'Pirate',
'Poppelhoffen',
'Elbow',
'Fluffy',
'Paphat'
]
var randName = function() {
var n = [Link];
return [
names[[Link]([Link]() * n)],
names[[Link]([Link]() * n)]
].join(' ');
}
var randAge = function(n) {
return [Link]([Link]() * n);
}
for (var i = 0; i < 1000; ++i) {
var person = {
name: randName(),
age: randAge(100)
}
if ([Link]() > 0.8) {
7
[Link] = {
name: randName(),
age: randAge(18)
}
}
[Link](person);
};
})();
- Utiliser find() pour trouver les personne âgées de 99 ans
- Trouver toutes les personnes éligibles à un pass bus (personnes de plus de 65 ans)
- Trouver tous les adolescents de plus de 12 ans et moins de20 ans
- Afficher les personnes qui ont un chat
Une autre opération classique est le tri des résultats, réalisable avec la fonction sort().
On doit indiquer les items de tri et leur attribuer une valeur de 1 pour un tri ascendant
et une valeur de -1 pour un tri descendant. On affiche ici les personnes d’au moins 32
ans dans l’ordre croissant de leur âge.
[Link]({ "age": { "$gte": 32} }, { "_id": 0, "name": 1, "age": 1 }).sort({
"age" : 1 })
Idem que précédemment, mais dans l’ordre décroissant.
[Link]({ "age": { "$gte": 32} }, { "_id": 0, "name": 1, "age": 1 }).sort({
"age" : -1 })
Bien évidemment, il est possible de mettre plusieurs critères de tri, comme ci-dessous
avec un tri par âge décroissant, et un tri alphabétique des noms (pour les personnes de
même âge).
[Link]({ "age": { "$gte": 32} }, { "_id": 0, "name": 1, "age": 1 }).sort({
"age" : -1, "name": 1 })
On peut aussi limiter le nombre de documents renvoyés par la fonction find() en lui
ajoutant la fonction limit(), comme ici où nous nous restreignons aux 5 premiers
résultats.
8
[Link]({age: { $gt: 65 }}). limit(5)
Il est souvent nécessaire de faire des dénombrements suite à des sélections, pour faire
des vérifications de code ou des estimations de charge (ou autre). La
fonction count() peut ainsi s’ajouter à la suite d’une fonction find() pour connaître la
taille du résultat.
[Link]({age: { $gt: 65 }}). .count()
Agrégats
En plus des recherches classiques d’informations, le calcul d’agrégat est très utilisé, pour
l’analyse, la modélisation ou la visualisation de données. Ce calcul s’effectue avec la
fonction aggregate(). Celle-ci prend en paramètre un tableau d’opérations (appelé
aussi pipeline), pouvant contenir les éléments suivants :
$group : regroupements et calculs à effectuer
$sort : tri sur les agrégats
…
Voici un premier exemple permettant un calcul pour toute la base. Ici, nous réalisons un
dénombrement (il fait la somme de la valeur 1 pour chaque document).
[Link]([
{ $group: { "_id": null, "nb": { $sum: 1 }}}
])
Bien évidemment, les calculs peuvent être plus complexes. Par exemple, nous cherchons
l’âge moyen des personnes.
[Link]([
{ $group: { "_id": null, "agemoy": { $avg: "$age" }}}
])
Bien évidemment, ces calculs d’agrégats peuvent se faire aussi en ajoutant des critères de
regroupement. Ici, nous cherchons le nombre de personnes par âge.
9
[Link]([
{ $group: { "_id": "$age", "nb": { $sum: 1 }}}
])
Ce résultat peut être trié en ajoutant l’action $sort dans le tableau, avec le même
mécanismes que précédemment (1 : ascendant, -1 : descendant).
[Link]([
{ $group: { "_id": "$age", "nb": { $sum: 1 }}},
{ $sort: { "nb": -1 }}
])
Comme vu précédemment, on peut faire tous les calculs d’agrégats classiques, comme ici
avec la somme ($sum), la moyenne ($avg), le minimum ($min) et le maximum ($max).
[Link]([
{ $group: {
"_id": "$age",
"nb": { $sum: 1 },
"ageTotale": { $sum: "$age" },
"ageMoyen": { $avg: "$age" },
"ageMinimum": { $min: "$age" },
"ageMaximum": { $max: "$age" }
}}
])
Exercice
1. Décompresser le fichier [Link]
2. Lancer l’importation du fichier :
Sudo mongoimport --db DBLP --collection publis …/[Link]
Exprimez des requêtes simples pour les recherches suivantes :
3. Liste de tous les livres (type « Book ») ;
4. Liste des publications depuis 2011 ;
10
5. Liste des livres depuis 2014 ;
6. Liste des publications de l’auteur « Toru Ishida » ;
7. Liste de tous les éditeurs (type « publisher »), distincts ;
8. Liste de tous les auteurs distincts ;
9. Trier les publications de « Toru Ishida » par titre de livre et par page de
début ;
10. Projeter le résultat sur le titre de la publication, et les pages ;
11. Compter le nombre de ses publications ;
12. Compter le nombre de publications depuis 2011 et par type ;
13. Compter le nombre de publications par auteur et trier le résultat par ordre
croissant
11