Opérations avancées¶
Agrégations¶
Fonction aggregate¶
MongoDB fournit la fonction aggregate qui permet de créer un pipeline (séquence) d'opérations ou stage (étape). Elle possède 2 paramètres : un tableau d'opérations et JSON optionnel pour les options d'exécution.
aggregate
> db.collection.aggregate([
{operation1:{}},
{operation2:{}}, ...
],
{
option1:value,
option2:value, ...
}
);
Opérateurs d'agrégation (stages)¶
Opérateurs simples¶
{$match: {<query>}}
: C’est une opération de filtrage exactement comme le premier paramètre de la requête find.
{$project: {champ1:1|0, ...}}
: C’est le second paramètre du find. Il donne le format de sortie des documents (projection). Il peut par ailleurs être utilisé pour changer le format d’origine.
{$sort: {champ1:1|-1,....}}
: Trier le résultat final sur les valeurs d’une clé choisi.
Exemples
Exemple1
Afficher le nom et l'adresse des restaurants dont le nom comporte "Staten Island".
//avec find
> db.restaurants.find({name:/Staten Island/},
{_id:0, name:1, address:1}
);
//avec aggregate
> db.restaurants.aggregate([
{$match:{name:/Staten Island/}},
{$project: {_id:0, name:1, address:1}}
]);
SELECT name, address
FROM restaurants
WHERE name like '%Staten Island%'
Trier le résultat selon l'ordre décroissant du nom.
> db.restaurants.aggregate([
{$match:{name:/Staten Island/}},
{$project: {_id:0, name:1, address:1}},
{$sort:{name:-1}}
]);
SELECT name, address
FROM restaurants
WHERE name like '%Staten Island%'
ORDER BY name DESC
Trier le résultat selon l'ordre décroissant du nom.
Groupage et agrégats¶
{$group: {_id: <expression>, <champAgrégé1>: { <accumulator1> : <expression1> },...}}
: C’est l’opération d’agrégation. Il va permettre de grouper les documents par valeur, et appliquer des fonctions d’agrégat. La sortie est une nouvelle collection avec les résultats de l’agrégation. _id est le champ du groupement (précéder le nom du champ valeur par $). accumulateur1 est une fonction d'agrégation : $min, $max, $sum, $avg
{$unwind : <$champTableau>}
: Crée n documents à partir d'un tableau. Il peut être considéré comme une jointure entre le document en cours de collection et le champ tableau. Le nom du champ est précédé par $.
Exemple2
Calculer le nombre de restaurants total.
> db.restaurants.aggregate([
{
$group:{_id:null, Total:{$sum:1}}
}
]);
SELECT count * as Total
FROM restaurants
Calculer le nombre de restaurants total par quartier.
> db.restaurants.aggregate([
{
$group:{_id:"$borough", Total:{$sum:1}}
}
]);
SELECT borough, count * as Total
FROM restaurants
GROUP BY borough
Calculer le score moyen des restaurants dont le nom contient "Staten Island". Puisque le score est dans le tableau grades, il faut transformer ce tableau avec $unwind. Chaque stage du pipeline peut être sauvegardé dans une variable pour être utilisé dans plusieurs requêtes.
> var filtrage = {$match:{name:/Staten Island/}};
> var decomposerGrades = {$unwind : "$grades"};
> var groupage = {$group:{_id:"$_id","Score moyen": {$avg:"$grades.score"}}};
> db.restaurants.aggregate([ filtrage, decomposerGrades, groupage]);
On suppose que grades est un table présente dans la base de données.
SELECT _id, AVG(grades.score) "Score moyen"
FROM restaurants JOIN grades
WHERE name like '%Staten Island%'
GROUP BY (_id)
Jointure¶
Nous présentons ici la syntaxe la plus simple pour une équi-jointure.
{$lookup: {from: <collection2>, localField: <champInterne>,foreignField: <chamCollection2>, as: <nouveauChampTableau>}}
: Cet opérateur effectue une jointure (left outer join) avec une autre collection de la base.
Exemple3
Soit une collection des managers des restaurants à laquelle on insère un document :
> db.createCollection("managers");
> db.managers.insert({name:"Alain Delon",age:50,res_id:"30075445"});
> db.managers.aggregate([
{
$lookup:{
from:"restaurants",
localField:"res_id",
foreignField:"restaurant_id",
as:"Restaurant"
}
}
]);
SELECT *, Restaurant
FROM managers
WHERE Restaurant in (SELECT *
FROM restaurants
WHERE restaurant_id = res_id)
Sortie¶
{$out: <collection> | {db:<base>, coll:<collection}}
: Cet opérateur spécifie la base et la collection où le résultat sera inséré.
Exemple 4
Pour enregistrer le résultat de la première requête de l'exemple 1.
> db.restaurants.aggregate([
{$match{name:/Staten Island/},
{$project: {_id:0, name:1, address:1}},
{$out:"staten"}
]);
CREATE TABLE staten AS(
SELECT name, address
FROM restaurants
WHERE name like '%Staten Island%'
);