MongoDB
Aggregazione MongoDB
Ricerca…
Esempi di query aggregate utili per lavoro e apprendimento
L'aggregazione viene utilizzata per eseguire complesse operazioni di ricerca dei dati nella query mongo che non possono essere eseguite nella normale query "trova".
Crea alcuni dati fittizi:
db.employees.insert({"name":"Adma","dept":"Admin","languages":["german","french","english","hindi"],"age":30, "totalExp":10});
db.employees.insert({"name":"Anna","dept":"Admin","languages":["english","hindi"],"age":35, "totalExp":11});
db.employees.insert({"name":"Bob","dept":"Facilities","languages":["english","hindi"],"age":36, "totalExp":14});
db.employees.insert({"name":"Cathy","dept":"Facilities","languages":["hindi"],"age":31, "totalExp":4});
db.employees.insert({"name":"Mike","dept":"HR","languages":["english", "hindi", "spanish"],"age":26, "totalExp":3});
db.employees.insert({"name":"Jenny","dept":"HR","languages":["english", "hindi", "spanish"],"age":25, "totalExp":3});
Esempi per argomento:
1. Corrispondenza: utilizzato per abbinare documenti (come la clausola SQL where)
db.employees.aggregate([{$match:{dept:"Admin"}}]);
Output:
{ "_id" : ObjectId("54982fac2e9b4b54ec384a0d"), "name" : "Adma", "dept" : "Admin", "languages" : [ "german", "french", "english", "hindi" ], "age" : 30, "totalExp" : 10 }
{ "_id" : ObjectId("54982fc92e9b4b54ec384a0e"), "name" : "Anna", "dept" : "Admin", "languages" : [ "english", "hindi" ], "age" : 35, "totalExp" : 11 }
2. Progetto: utilizzato per popolare i valori del campo specifico
fase del progetto includerà automaticamente il campo _id a meno che non si specifichi di disabilitare.
db.employees.aggregate([{$match:{dept:"Admin"}}, {$project:{"name":1, "dept":1}}]);
Output:
{ "_id" : ObjectId("54982fac2e9b4b54ec384a0d"), "name" : "Adma", "dept" : "Admin" }
{ "_id" : ObjectId("54982fc92e9b4b54ec384a0e"), "name" : "Anna", "dept" : "Admin" }
db.employees.aggregate({$project: {'_id':0, 'name': 1}})
Output:
{ "name" : "Adma" }
{ "name" : "Anna" }
{ "name" : "Bob" }
{ "name" : "Cathy" }
{ "name" : "Mike" }
{ "name" : "Jenny" }
3. Gruppo: $ group è usato per raggruppare i documenti per campo specifico, qui i documenti sono raggruppati per il valore del campo "dept". Un'altra caratteristica utile è che puoi raggruppare per null, significa che tutti i documenti saranno aggregati in uno solo.
db.employees.aggregate([{$group:{"_id":"$dept"}}]);
{ "_id" : "HR" }
{ "_id" : "Facilities" }
{ "_id" : "Admin" }
db.employees.aggregate([{$group:{"_id":null, "totalAge":{$sum:"$age"}}}]);
Output:
{ "_id" : null, "noOfEmployee" : 183 }
4. Somma: $ somma viene utilizzata per contare o sommare i valori all'interno di un gruppo.
db.employees.aggregate([{$group:{"_id":"$dept", "noOfDept":{$sum:1}}}]);
Output:
{ "_id" : "HR", "noOfDept" : 2 }
{ "_id" : "Facilities", "noOfDept" : 2 }
{ "_id" : "Admin", "noOfDept" : 2 }
5. Media: calcola la media del valore del campo specifico per gruppo.
db.employees.aggregate([{$group:{"_id":"$dept", "noOfEmployee":{$sum:1}, "avgExp":{$avg:"$totalExp"}}}]);
Output:
{ "_id" : "HR", "noOfEmployee" : 2, "totalExp" : 3 }
{ "_id" : "Facilities", "noOfEmployee" : 2, "totalExp" : 9 }
{ "_id" : "Admin", "noOfEmployee" : 2, "totalExp" : 10.5 }
6. Minimo: trova il valore minimo di un campo in ciascun gruppo.
db.employees.aggregate([{$group:{"_id":"$dept", "noOfEmployee":{$sum:1}, "minExp":{$min:"$totalExp"}}}]);
Output:
{ "_id" : "HR", "noOfEmployee" : 2, "totalExp" : 3 }
{ "_id" : "Facilities", "noOfEmployee" : 2, "totalExp" : 4 }
{ "_id" : "Admin", "noOfEmployee" : 2, "totalExp" : 10 }
7. Massimo: trova il valore massimo di un campo in ciascun gruppo.
db.employees.aggregate([{$group:{"_id":"$dept", "noOfEmployee":{$sum:1}, "maxExp":{$max:"$totalExp"}}}]);
Output:
{ "_id" : "HR", "noOfEmployee" : 2, "totalExp" : 3 }
{ "_id" : "Facilities", "noOfEmployee" : 2, "totalExp" : 14 }
{ "_id" : "Admin", "noOfEmployee" : 2, "totalExp" : 11 }
8. Ottenere il valore del campo specifico dal primo e dall'ultimo documento di ciascun gruppo: Funziona bene quando il risultato del doucument è ordinato.
db.employees.aggregate([{$group:{"_id":"$age", "lasts":{$last:"$name"}, "firsts":{$first:"$name"}}}]);
Output:
{ "_id" : 25, "lasts" : "Jenny", "firsts" : "Jenny" }
{ "_id" : 26, "lasts" : "Mike", "firsts" : "Mike" }
{ "_id" : 35, "lasts" : "Cathy", "firsts" : "Anna" }
{ "_id" : 30, "lasts" : "Adma", "firsts" : "Adma" }
9. Minimo con il massimo:
db.employees.aggregate([{$group:{"_id":"$dept", "noOfEmployee":{$sum:1}, "maxExp":{$max:"$totalExp"}, "minExp":{$min: "$totalExp"}}}]);
Output:
{ "_id" : "HR", "noOfEmployee" : 2, "maxExp" : 3, "minExp" : 3 }
{ "_id" : "Facilities", "noOfEmployee" : 2, "maxExp" : 14, "minExp" : 4 }
{ "_id" : "Admin", "noOfEmployee" : 2, "maxExp" : 11, "minExp" : 10 }
10. Aggiungi e aggiungiToSet: Push aggiunge il valore di un campo di ogni documento in un gruppo a un array utilizzato per proiettare i dati in formato array, addToSet è simlar to push ma omette i valori duplicati.
db.employees.aggregate([{$group:{"_id":"dept", "arrPush":{$push:"$age"}, "arrSet": {$addToSet:"$age"}}}]);
Output:
{ "_id" : "dept", "arrPush" : [ 30, 35, 35, 35, 26, 25 ], "arrSet" : [ 25, 26, 35, 30 ] }
11. Svolgimento: utilizzato per creare più documenti in memoria per ciascun valore nel campo del tipo di matrice specificato, quindi è possibile eseguire un'ulteriore aggregazione in base a tali valori.
db.employees.aggregate([{$match:{"name":"Adma"}}, {$unwind:"$languages"}]);
Output:
{ "_id" : ObjectId("54982fac2e9b4b54ec384a0d"), "name" : "Adma", "dept" : "HR", "languages" : "german", "age" : 30, "totalExp" : 10 }
{ "_id" : ObjectId("54982fac2e9b4b54ec384a0d"), "name" : "Adma", "dept" : "HR", "languages" : "french", "age" : 30, "totalExp" : 10 }
{ "_id" : ObjectId("54982fac2e9b4b54ec384a0d"), "name" : "Adma", "dept" : "HR", "languages" : "english", "age" : 30, "totalExp" : 10 }
{ "_id" : ObjectId("54982fac2e9b4b54ec384a0d"), "name" : "Adma", "dept" : "HR", "languages" : "hindi", "age" : 30, "totalExp" : 10 }
12. Ordinamento:
db.employees.aggregate([{$match:{dept:"Admin"}}, {$project:{"name":1, "dept":1}}, {$sort: {name: 1}}]);
Output:
{ "_id" : ObjectId("57ff3e553dedf0228d4862ac"), "name" : "Adma", "dept" : "Admin" }
{ "_id" : ObjectId("57ff3e5e3dedf0228d4862ad"), "name" : "Anna", "dept" : "Admin" }
db.employees.aggregate([{$match:{dept:"Admin"}}, {$project:{"name":1, "dept":1}}, {$sort: {name: -1}}]);
Output:
{ "_id" : ObjectId("57ff3e5e3dedf0228d4862ad"), "name" : "Anna", "dept" : "Admin" }
{ "_id" : ObjectId("57ff3e553dedf0228d4862ac"), "name" : "Adma", "dept" : "Admin" }
13. Salta:
db.employees.aggregate([{$match:{dept:"Admin"}}, {$project:{"name":1, "dept":1}}, {$sort: {name: -1}}, {$skip:1}]);
Output:
{ "_id" : ObjectId("57ff3e553dedf0228d4862ac"), "name" : "Adma", "dept" : "Admin" }
14. Limite:
db.employees.aggregate([{$match:{dept:"Admin"}}, {$project:{"name":1, "dept":1}}, {$sort: {name: -1}}, {$limit:1}]);
Output:
{ "_id" : ObjectId("57ff3e5e3dedf0228d4862ad"), "name" : "Anna", "dept" : "Admin" }
15. Operatore di comparazione in proiezione:
db.employees.aggregate([{$match:{dept:"Admin"}}, {$project:{"name":1, "dept":1, age: {$gt: ["$age", 30]}}}]);
Output:
{ "_id" : ObjectId("57ff3e553dedf0228d4862ac"), "name" : "Adma", "dept" : "Admin", "age" : false }
{ "_id" : ObjectId("57ff3e5e3dedf0228d4862ad"), "name" : "Anna", "dept" : "Admin", "age" : true }
16. Operatore di confronto nella partita:
db.employees.aggregate([{$match:{dept:"Admin", age: {$gt:30}}}, {$project:{"name":1, "dept":1}}]);
Output:
{ "_id" : ObjectId("57ff3e5e3dedf0228d4862ad"), "name" : "Anna", "dept" : "Admin" }
Elenco degli operatori di confronto: $ cmp, $ eq, $ gt, $ gte, $ lt, $ lte e $ ne
17. Operatore di aggregazione booleana in proiezione:
db.employees.aggregate([{$match:{dept:"Admin"}}, {$project:{"name":1, "dept":1, age: { $and: [ { $gt: [ "$age", 30 ] }, { $lt: [ "$age", 36 ] } ] }}}]);
Output:
{ "_id" : ObjectId("57ff3e553dedf0228d4862ac"), "name" : "Adma", "dept" : "Admin", "age" : false }
{ "_id" : ObjectId("57ff3e5e3dedf0228d4862ad"), "name" : "Anna", "dept" : "Admin", "age" : true }
18. Operatore di aggregazione booleana in corrispondenza:
db.employees.aggregate([{$match:{dept:"Admin", $and: [{age: { $gt: 30 }}, {age: {$lt: 36 }} ] }}, {$project:{"name":1, "dept":1, age: { $and: [ { $gt: [ "$age", 30 ] }, { $lt: [ "$age", 36 ] } ] }}}]);
Output:
{ "_id" : ObjectId("57ff3e5e3dedf0228d4862ad"), "name" : "Anna", "dept" : "Admin", "age" : true }
Elenco di operatori di aggregazione booleana: $ e, $ o e $ non.
Completa refrence: https://docs.mongodb.com/v3.2/reference/operator/aggregation/
Esempio di Java e Spring
Questo è un codice di esempio per creare ed eseguire la query aggregata in MongoDB usando Spring Data.
try {
MongoClient mongo = new MongoClient();
DB db = mongo.getDB("so");
DBCollection coll = db.getCollection("employees");
//Equivalent to $match
DBObject matchFields = new BasicDBObject();
matchFields.put("dept", "Admin");
DBObject match = new BasicDBObject("$match", matchFields);
//Equivalent to $project
DBObject projectFields = new BasicDBObject();
projectFields.put("_id", 1);
projectFields.put("name", 1);
projectFields.put("dept", 1);
projectFields.put("totalExp", 1);
projectFields.put("age", 1);
projectFields.put("languages", 1);
DBObject project = new BasicDBObject("$project", projectFields);
//Equivalent to $group
DBObject groupFields = new BasicDBObject("_id", "$dept");
groupFields.put("ageSet", new BasicDBObject("$addToSet", "$age"));
DBObject employeeDocProjection = new BasicDBObject("$addToSet", new BasicDBObject("totalExp", "$totalExp").append("age", "$age").append("languages", "$languages").append("dept", "$dept").append("name", "$name"));
groupFields.put("docs", employeeDocProjection);
DBObject group = new BasicDBObject("$group", groupFields);
//Sort results by age
DBObject sort = new BasicDBObject("$sort", new BasicDBObject("age", 1));
List<DBObject> aggregationList = new ArrayList<>();
aggregationList.add(match);
aggregationList.add(project);
aggregationList.add(group);
aggregationList.add(sort);
AggregationOutput output = coll.aggregate(aggregationList);
for (DBObject result : output.results()) {
BasicDBList employeeList = (BasicDBList) result.get("docs");
BasicDBObject employeeDoc = (BasicDBObject) employeeList.get(0);
String name = employeeDoc.get("name").toString();
System.out.println(name);
}
}catch (Exception ex){
ex.printStackTrace();
}
Vedi il valore "resultSet" in formato JSON per capire il formato di output:
[{
"_id": "Admin",
"ageSet": [35.0, 30.0],
"docs": [{
"totalExp": 11.0,
"age": 35.0,
"languages": ["english", "hindi"],
"dept": "Admin",
"name": "Anna"
}, {
"totalExp": 10.0,
"age": 30.0,
"languages": ["german", "french", "english", "hindi"],
"dept": "Admin",
"name": "Adma"
}]
}]
"ResultSet" contiene una voce per ogni gruppo, "ageSet" contiene l'elenco di età di ciascun dipendente di quel gruppo, "_id" contiene il valore del campo che viene utilizzato per il raggruppamento e "docs" contiene i dati di ciascun dipendente di quel gruppo che può essere utilizzato nel nostro codice e nell'interfaccia utente.
Ottieni dati di esempio
Per ottenere dati casuali da una certa collezione, fai riferimento a $sample
aggregation.
db.emplyees.aggregate({ $sample: { size:1 } })
dove la size
corrisponde al numero di elementi da selezionare.
Left Outer Join con aggregazione ($ Lookup)
let col_1 = db.collection('col_1');
let col_2 = db.collection('col_2');
col_1 .aggregate([
{ $match: { "_id": 1 } },
{
$lookup: {
from: "col_2",
localField: "id",
foreignField: "id",
as: "new_document"
}
}
],function (err, result){
res.send(result);
});
Questa funzione è stata appena rilasciata nella versione 3.2 di mongodb, che offre all'utente una fase per unire una raccolta con gli attributi corrispondenti di un'altra raccolta
Documentazione di Mongodb $ LookUp