MongoDB
Zbiór
Szukaj…
Wprowadzenie
Operacje Aggregations
przetwarzają rekordy danych i zwracają obliczone wyniki. Operacje agregujące grupują wartości z wielu dokumentów razem i mogą wykonywać różne operacje na zgrupowanych danych w celu zwrócenia pojedynczego wyniku. MongoDB zapewnia trzy sposoby przeprowadzania agregacji: potok agregacji, funkcja zmniejszania mapy i metody agregacji o jednym celu.
Z podręcznika Mongo https://docs.mongodb.com/manual/aggregation/
Składnia
- db.collection.aggregate (potok, opcje)
Parametry
Parametr | Detale |
---|---|
rurociąg | tablica (sekwencja operacji lub etapów agregacji danych) |
opcje | dokument (opcjonalnie, dostępny tylko wtedy, gdy potok występuje jako tablica) |
Uwagi
Struktura agregacji w MongoDB służy do osiągnięcia wspólnej funkcjonalności GROUP BY
SQL.
Rozważ następujące wstawki w nazwanych transactions
kolekcji dla każdego przykładu.
> db.transactions.insert({ cr_dr : "D", amount : 100, fee : 2});
> db.transactions.insert({ cr_dr : "C", amount : 100, fee : 2});
> db.transactions.insert({ cr_dr : "C", amount : 10, fee : 2});
> db.transactions.insert({ cr_dr : "D", amount : 100, fee : 4});
> db.transactions.insert({ cr_dr : "D", amount : 10, fee : 2});
> db.transactions.insert({ cr_dr : "C", amount : 10, fee : 4});
> db.transactions.insert({ cr_dr : "D", amount : 100, fee : 2});
Liczyć
Jak uzyskać liczbę transakcji debetowych i kredytowych? Jednym ze sposobów na to jest użycie funkcji count()
jak poniżej.
> db.transactions.count({cr_dr : "D"});
lub
> db.transactions.find({cr_dr : "D"}).length();
Ale co, jeśli nie znasz możliwych wartości cr_dr
z góry. Tutaj zaczyna się gra Aggregation Framework. Zobacz poniższe zapytanie agregujące.
> db.transactions.aggregate(
[
{
$group : {
_id : '$cr_dr', // group by type of transaction
// Add 1 for each document to the count for this type of transaction
count : {$sum : 1}
}
}
]
);
I wynik jest taki
{
"_id" : "C",
"count" : 3
}
{
"_id" : "D",
"count" : 5
}
Suma
Jak uzyskać sumę amount
? Zobacz poniższe zapytanie zagregowane.
> db.transactions.aggregate(
[
{
$group : {
_id : '$cr_dr',
count : {$sum : 1}, //counts the number
totalAmount : {$sum : '$amount'} //sums the amount
}
}
]
);
I wynik jest taki
{
"_id" : "C",
"count" : 3.0,
"totalAmount" : 120.0
}
{
"_id" : "D",
"count" : 5.0,
"totalAmount" : 410.0
}
Kolejna wersja, która sumuje amount
i fee
.
> db.transactions.aggregate(
[
{
$group : {
_id : '$cr_dr',
count : {$sum : 1},
totalAmount : {$sum : { $sum : ['$amount', '$fee']}}
}
}
]
);
I wynik jest taki
{
"_id" : "C",
"count" : 3.0,
"totalAmount" : 128.0
}
{
"_id" : "D",
"count" : 5.0,
"totalAmount" : 422.0
}
Średni
Jak uzyskać średnią kwotę transakcji debetowych i kredytowych?
> db.transactions.aggregate(
[
{
$group : {
_id : '$cr_dr', // group by type of transaction (debit or credit)
count : {$sum : 1}, // number of transaction for each type
totalAmount : {$sum : { $sum : ['$amount', '$fee']}}, // sum
averageAmount : {$avg : { $sum : ['$amount', '$fee']}} // average
}
}
]
)
Wynik to
{
"_id" : "C", // Amounts for credit transactions
"count" : 3.0,
"totalAmount" : 128.0,
"averageAmount" : 40.0
}
{
"_id" : "D", // Amounts for debit transactions
"count" : 5.0,
"totalAmount" : 422.0,
"averageAmount" : 82.0
}
Operacje na tablicach.
Jeśli chcesz pracować z wpisami danych w tablicach, musisz najpierw odłączyć tablicę. Operacja odwijania tworzy dokument dla każdego wpisu w tablicy. Kiedy masz dużo dokumentów z dużymi tablicami, zobaczysz eksplozję w liczbie dokumentów.
{ "_id" : 1, "item" : "myItem1", sizes: [ "S", "M", "L"] }
{ "_id" : 2, "item" : "myItem2", sizes: [ "XS", "M", "XL"] }
db.inventory.aggregate( [ { $unwind : "$sizes" }] )
Ważną uwagą jest to, że jeśli dokument nie zawiera tablicy, zostanie utracony. Od wersji 3.2 Mongo jest dodana opcja odprężania „preserveNullAndEmptyArrays”. Ta opcja zapewnia zachowanie dokumentu w przypadku braku tablicy.
{ "_id" : 1, "item" : "myItem1", sizes: [ "S", "M", "L"] }
{ "_id" : 2, "item" : "myItem2", sizes: [ "XS", "M", "XL"] }
{ "_id" : 3, "item" : "myItem3" }
db.inventory.aggregate( [ { $unwind : { path: "$sizes", includeArrayIndex: "arrayIndex" } }] )
Mecz
Jak napisać zapytanie, aby uzyskać wszystkie działy, w których średni wiek pracowników zarabiających mniej niż 70000 USD jest wyższy lub równy 35?
W tym celu musimy napisać zapytanie pasujące do pracowników, których wynagrodzenie jest niższe lub równe 70000 USD. Następnie dodaj etap agregacji, aby pogrupować pracowników według działów. Następnie dodaj akumulator z polem o nazwie np. Average_age, aby znaleźć średni wiek na dział przy użyciu akumulatora $ Avg i poniżej istniejącego $ match, a agregaty $ group dodaj kolejny agregat $ match, abyśmy otrzymywali wyniki tylko ze średnią większy lub równy 35.
db.employees.aggregate([
{"$match": {"salary": {"$lte": 70000}}},
{"$group": {"_id": "$dept",
"average_age": {"$avg": "$age"}
}
},
{"$match": {"average_age": {"$gte": 35}}}
])
Wynik to:
{
"_id": "IT",
"average_age": 31
}
{
"_id": "Customer Service",
"average_age": 34.5
}
{
"_id": "Finance",
"average_age": 32.5
}
Usuń dokumenty, które mają zduplikowane pole w kolekcji (dedupe)
Zauważ, że opcja allowDiskUse: true jest opcjonalna, ale pomoże złagodzić problemy z pamięcią, ponieważ ta agregacja może być operacją intensywnie korzystającą z pamięci, jeśli Twój rozmiar kolekcji jest duży - dlatego zalecam, aby zawsze go używać.
var duplicates = [];
db.transactions.aggregate([
{ $group: {
_id: { cr_dr: "$cr_dr"},
dups: { "$addToSet": "$_id" },
count: { "$sum": 1 }
}
},
{ $match: {
count: { "$gt": 1 }
}}
],allowDiskUse: true}
)
.result
.forEach(function(doc) {
doc.dups.shift();
doc.dups.forEach( function(dupId){
duplicates.push(dupId);
}
)
})
// printjson(duplicates);
// Remove all duplicates in one go
db.transactions.remove({_id:{$in:duplicates}})