aggregation framework w MongoDB 3.4 i nowsze oferuje operatorowi $reduce
który efektywnie oblicza całkowitą bez konieczności stosowania dodatkowych rurociągów. Rozważ użycie go jako wyrażenia, aby zwrócić całkowitą liczbę ocen i uzyskać liczbę ocen za pomocą $size
. Wraz z $addFields
średnia może zatem być obliczana za pomocą operatora arytmetyczną $divide
jak we wzorze average = total ratings/number of ratings
:
db.collection.aggregate([
{
"$addFields": {
"rating_average": {
"$divide": [
{ // expression returns total
"$reduce": {
"input": "$ratings",
"initialValue": 0,
"in": { "$add": ["$$value", "$$this.rating"] }
}
},
{ // expression returns ratings count
"$cond": [
{ "$ne": [ { "$size": "$ratings" }, 0 ] },
{ "$size": "$ratings" },
1
]
}
]
}
}
}
])
próbek wyjściowych
{
"_id" : ObjectId("58ab48556da32ab5198623f4"),
"title" : "The Hobbit",
"ratings" : [
{
"title" : "best book ever",
"rating" : 5.0
},
{
"title" : "good book",
"rating" : 3.5
}
],
"rating_average" : 4.25
}
przypadku starszych wersjach musisz najpierw zastosować operatora $unwind
na ratings
najpierw pole tablicy jako początkowy krok agregacji potoków. Spowoduje to dekonstrukcję pola tablicy ratings
z dokumentów wejściowych, aby wyprowadzić dokument dla każdego elementu. Każdy dokument wyjściowy zastępuje tablicę wartością elementu.
Drugi etap Rurociąg operator $group
które dokumenty wprowadzania grupy przez _id
i title
kluczy identyfikatora ekspresji i stosuje się żądany ekspresji $avg
akumulatora z każdej grupy oblicza się średnią. Istnieje inny operator akumulatora $push
, który zachowuje pole oryginalnej tablicy ocen, zwracając tablicę wszystkich wartości, które wynikają z zastosowania wyrażenia do każdego dokumentu w powyższej grupie.
Ostatnim etapem procesu jest operator $project
, który zmienia kształt każdego dokumentu w strumieniu, na przykład dodając nowe pole ratings_average
.
Tak więc, jeśli na przykład masz przykładowy dokument w swojej kolekcji (jak z góry i tak poniżej):
db.collection.insert({
"title": "The Hobbit",
"ratings": [
{
"title": "best book ever",
"rating": 5
},
{
"title": "good book",
"rating": 3.5
}
]
})
Aby obliczyć średnią ocen tablicy i wystająca wartość w innej dziedzinie ratings_average
, można wówczas stosuje się następujące agregacji rurociągu:
db.collection.aggregate([
{
"$unwind": "$ratings"
},
{
"$group": {
"_id": {
"_id": "$_id",
"title": "$title"
},
"ratings":{
"$push": "$ratings"
},
"ratings_average": {
"$avg": "$ratings.rating"
}
}
},
{
"$project": {
"_id": 0,
"title": "$_id.title",
"ratings_average": 1,
"ratings": 1
}
}
])
Wynik:
/* 1 */
{
"result" : [
{
"ratings" : [
{
"title" : "best book ever",
"rating" : 5
},
{
"title" : "good book",
"rating" : 3.5
}
],
"ratings_average" : 4.25,
"title" : "The Hobbit"
}
],
"ok" : 1
}
Dziękuję, chridam :) – retrobitguy
@retrobitguy Bez obaw :-) – chridam
To było bardzo pomocne i jasne! Wielkie dzięki! – retrobitguy