Le framework d’agrégation est un ensemble d’outils d’analyse au sein de MongoDB qui permettent d’effectuer des analyses et rapports des documents d’une ou plusieurs collections de MongoDB.
Les agrégations se font sur un principe de pipeline: on prend les données d’une collection MongoDB, puis on effectue des opérations dessus à travers plusieurs étapes. Chaque étape prend en entrée ce que l’étape précédente retourne. Toutes les entrées et sorties sont un flux de documents.
La pipeline d’agrégation est un tableau contenant des étapes, chaque étape utilisant un opérateur d’agrégation.
Pour récupérer tous les documents qui matchent une requête, on utilise $match
(même principe que find, même syntaxe)
db.companies.aggregate([{ $match: { founded_year: 2004 } })
Pour effectuer une projection (sélectionner les champs à récupérer), on utilise $project
db.companies.aggregate([
{ $match: { founded_year: 2004 }},
{ $project : {
_id: 0,
name: 1,
founded_year: 1
} }
])
On peut sélectionner un champs sous un autre nom (même principe que AS
avec MySQL):
db.companies.aggregate([
{ $match: { "funding_rounds.investments.financial_org.permalink": "greylock" }},
{ $project: {
_id: 0,
name: 1,
funders: "$funding_rounds.investments.financial_org.permalink"
}}
])
db.companies.aggregate([
{ $match: { "funding_rounds.investments.financial_org.permalink": "greylock" }},
{ $project: {
company: 0,
name: 1,
founded: {
year: "$founded_year",
month: "$founded_month",
day: "$founded_day"
}
} }
])
Permet de sélectionner un sous-ensemble des éléments d’un tableau en fonction d’un certain nombre de critères de filtrage. Utiliser $$
dans la condition pour désigner la variable définie dans l’expression as
.
db.companies.aggregate([
{ $match: {"funding_rounds.investments.financial_org.permalink": "greylock"} },
{ $project : {
_id: 0,
name: 1,
rounds: {
$filter: {
input: "$funding_rounds",
as: "round",
cond: { $gte:[ "$$round.raised_amount", 1000000 ] }
}
}
}}
])
Permet de récupérer un élément dans un sous-tableau en se basant sur son index.
db.companies.aggregate([
{ $project : {
_id: 0,
name: 1,
first_round: { $arrayElemAt: [ "$funding_rounds", 0 ] },
last_round: { $arrayElemAt: [ "$funding_rounds", -1 ] }
} }
])
Permet de récupérer un sous-ensemble de tableau, x éléments à partir d’un index donné.
db.companies.aggregate([
{ $project : {
_id: 0,
name: 1,
early_rounds: { $slice: [ "$funding_rounds", 0, 3 ] }
} }
])
Retourne le nombre d’éléments d’un tableau.
db.companies.aggregate([
{ $project : {
_id: 0,
name: 1,
total_rounds: { $size: "$funding_rounds" }
} }
])
Permet de calculer une somme.
db.companies.aggregate([
{ $project : {
_id: 0,
name: 1,
num_rounds: { $sum: 1 },
total_raised: { $sum: "$funding_rounds.raised_amount" }
} }
])
Retourne la valeur maximale.
db.companies.aggregate([
{ $project : {
_id: 0,
name: 1,
largest_round: { $max: "$funding_rounds.raised_amount" }
} }
])
Retourne la valeur minimale.
Retourne la valeur moyenne.
Permet de limiter le nombre de résultats récupérés.
db.companies.aggregate([
{ $match: { founded_year: 2004 } },
{ $limit: 5 },
{ $project : {
_id: 0,
name: 1,
founded_year: 1
} }
])
Permet de trier les résultats
db.companies.aggregate([
{ $match: { founded_year: 2004 } },
{ $sort: { name: 1 } },
{ $limit: 5 },
{ $project : {
_id: 0,
name: 1,
founded_year: 1
} }
])
On peut trier sur les champs d’un sous-objet
$sort: { "funding_rounds.founded_year": 1 }
Permet d’éclater un document en plusieurs documents, en se basant sur les valeurs d’un tableau.
C’est à dire remplacer
{ "name": "a", "key": ["elem1", "elem2", "elem3"] }
par
{ "name": "a", "key": "elem1" }
{ "name": "a", "key": "elem2" }
{ "name": "a", "key": "elem3" }
Exemple:
db.companies.aggregate([
{ $match: { "funding_rounds.investments.financial_org.permalink": "greylock" }},
{ $unwind: "$funding_rounds" },
{ $unwind: "$funding_rounds.investments" },
{ $match: { "$funding_rounds.investments.financial_org.permalink": "greylock" }},
{ $project : {
_id: 0,
name: 1,
fundingOrganization: "$funding_rounds.investments.financial_org.permalink",
amount: "$funding_rounds.raised_amount",
year: "$funding_rounds.funded_year"
}}
])
Permet d’agréger les valeurs de plusieurs documents pour effectuer une opération d’agrégation dessus, comme le calcul d’une moyenne par exemple.
Similaire au GROUP
MySQL.
// Calcule la moyenne du nombre d'employés
// Groupé par année de création de l'entreprise
db.companies.aggregate([
{ $group: {
_id: { founded_year: "$founded_year" },
average_number_of_employees: { $avg: "$number_of_employees" }
},
{ $sort: { average_number_of_employees: -1 } }
])
// Calcule le nombre de fois où un employé
// À été associé à une entreprise
db.companies.aggregate([
{ $match: { "relationships.person": { $ne: null } } },
{ $project: { relationships: 1, _id: 0 } },
{ $unwind: "$relationships" },
{ $group: {
_id: "$relationships.person",
count: { $sum: 1 }
} },
{ $sort: { count: -1 } }
])
Le groupe est effectué sur le champ _id
.
On peut grouper les documents sur le champ founded_year
en utilisant
{ _id: "founded_year" }
Le nom du groupe sera alors _id
.
Pour nommer le groupe founded_year
, utiliser
{ _id: { founded_year: "$founded_year" }}
On peut grouper sur plusieurs champs
{ _id: { founded_year: "$founded_year", category_code: "$category_code" }}
Ou même un sous-champ
{ _id: { ipo_year: "$ipo.pub_year" } }
$push
est uniquement disponible à l’intérieur de $group
.
Il permet de créer un tableau pour chaque groupe, contenant les champs sélectionnés des documents du groupe.
db.sales.aggregate([
{ $group: {
_id: {
day: { $dayOfYear: "$date"},
year: { $year: "$date" }
},
itemsSold: {
$push: { item: "$item", quantity: "$quantity" }
}
}}
])
input:
{ "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "date" : ISODate("2014-01-01T08:00:00Z") }
{ "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1, "date" : ISODate("2014-02-03T09:00:00Z") }
{ "_id" : 3, "item" : "xyz", "price" : 5, "quantity" : 5, "date" : ISODate("2014-02-03T09:05:00Z") }
{ "_id" : 4, "item" : "abc", "price" : 10, "quantity" : 10, "date" : ISODate("2014-02-15T08:00:00Z") }
{ "_id" : 5, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-02-15T09:05:00Z") }
{ "_id" : 6, "item" : "xyz", "price" : 5, "quantity" : 5, "date" : ISODate("2014-02-15T12:05:10Z") }
{ "_id" : 7, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-02-15T14:12:12Z") }
output:
{
"_id" : { "day" : 46, "year" : 2014 },
"itemsSold" : [
{ "item" : "abc", "quantity" : 10 },
{ "item" : "xyz", "quantity" : 10 },
{ "item" : "xyz", "quantity" : 5 },
{ "item" : "xyz", "quantity" : 10 }
]
}
{
"_id" : { "day" : 34, "year" : 2014 },
"itemsSold" : [
{ "item" : "jkl", "quantity" : 1 },
{ "item" : "xyz", "quantity" : 5 }
]
}
{
"_id" : { "day" : 1, "year" : 2014 },
"itemsSold" : [ { "item" : "abc", "quantity" : 2 } ]
}