MongoDB
Агрегация MongoDB
Поиск…
Совокупные примеры запросов, полезные для работы и обучения
Агрегация используется для выполнения сложных операций поиска данных в запросе mongo, которые не могут быть выполнены в обычном запросе «найти».
Создайте некоторые фиктивные данные:
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});
Примеры по теме:
1. Match: используется для сопоставления документов (например, предложения 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. Проект: используется для заполнения значений (значений) конкретного поля
этап проекта будет включать поле _id автоматически, если вы не укажете, чтобы отключить его.
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. Группа: группа $ group используется для группировки документов по определенному полю, здесь документы сгруппированы по значению поля «dept». Еще одна полезная функция состоит в том, что вы можете группировать по нулевому значению, это означает, что все документы будут объединены в один.
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. Сумма: $ sum используется для подсчета или суммирования значений внутри группы.
db.employees.aggregate([{$group:{"_id":"$dept", "noOfDept":{$sum:1}}}]);
Output:
{ "_id" : "HR", "noOfDept" : 2 }
{ "_id" : "Facilities", "noOfDept" : 2 }
{ "_id" : "Admin", "noOfDept" : 2 }
5. Среднее значение: вычисляет среднее значение конкретного поля для каждой группы.
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. Minimum: определяет минимальное значение поля в каждой группе.
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. Максимум: находит максимальное значение поля в каждой группе.
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. Получение значения конкретного поля из первого и последнего документа каждой группы: Хорошо работает, когда результат выполнения сортировки сортируется.
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. Минимальная сумма с максимумом:
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. Push и addToSet: Push добавляет значение поля каждого документа в группу к массиву, используемому для проектирования данных в формате массива, добавление addToSet равносильно нажатию, но оно не позволяет дублировать значения.
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. Unwind: используется для создания нескольких документов в памяти для каждого значения в указанном поле типа массива, тогда мы можем выполнить дальнейшую агрегацию на основе этих значений.
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. Сортировка:
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. Пропустить:
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. Предел:
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. Оператор сравнения в проекции:
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. Оператор сравнения в матче:
db.employees.aggregate([{$match:{dept:"Admin", age: {$gt:30}}}, {$project:{"name":1, "dept":1}}]);
Output:
{ "_id" : ObjectId("57ff3e5e3dedf0228d4862ad"), "name" : "Anna", "dept" : "Admin" }
Список операторов сравнения: $ cmp, $ eq, $ gt, $ gte, $ lt, $ lte и $ ne
17. Оператор булевой агрегирования в проекции:
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. Оператор булевой агрегирования в матче:
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 }
Список логических операторов агрегирования: $ и, $ или, и $ not.
Полное refrence: https://docs.mongodb.com/v3.2/reference/operator/aggregation/
Пример Java и Spring
Это пример кода для создания и выполнения агрегированного запроса в MongoDB с использованием 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();
}
См. Значение «resultSet» в формате JSON для понимания формата вывода:
[{
"_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» содержит одну запись для каждой группы, «ageSet» содержит список возраста каждого сотрудника этой группы, «_id» содержит значение поля, которое используется для группировки, и «docs» содержит данные каждого сотрудника этой группы, которая может использоваться в нашем собственном коде и пользовательском интерфейсе.
Получить образцы данных
Чтобы получить случайные данные из определенной коллекции, обратитесь к агрегации $sample
.
db.emplyees.aggregate({ $sample: { size:1 } })
где size
означает количество элементов для выбора.
Left Outer Присоединиться к агрегации ($ 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);
});
Эта функция была недавно выпущена в версии mongodb 3.2 , которая дает пользователю возможность присоединиться к одной коллекции с соответствующими атрибутами из другой коллекции
Документация LookOp от Mongodb