Struktura danych tutaj nie jest dobrą implementacją, jest wiele problemów z jej strukturą i jest całkowicie nieodpowiednia do agregacji. Główne problemy to:
-
Twoja struktura tak naprawdę nie używa żadnych tablic, w tej chwili tak nie jest
-
Wszystkie konkretne nazwy kluczy stanowią prawdziwy problem i można tego uniknąć.
W związku z tym jedynym sposobem na przejście tego rodzaju struktury jest użycie JavaScript z mapReduce.
Definiowanie mapera:
var mapper = function () {
for ( var n in this.versions ) {
for ( var k in this.versions[n].content ) {
if (
( k != 'confirmed' ) ||
( k != 'visited' ) )
emit(
{
type: this.chairtype,
key: k
},
this.versions[n].content[k]
);
}
}
};
Więc to co robi, to przechodzenie przez każdy z wpisów wersji, a następnie przez wszystkie w treści. Klucz jest emitowany dla każdego z żądanych kluczy treści, a także przez klucz „chairtype”. A wartością jest ta pasująca wartość.
A potem reduktor:
var reducer = function (key,values) {
return ( Array.sum( values ) != 0 )
? Array.sum( values ) / values.length : 0;
};
Co jest po prostu prostym sposobem na wytworzenie średniej ze wszystkich wartości przychodzących do mapowania z tym samym kluczem.
Więc chociaż powinno to działać dobrze, powinieneś zmienić swoją strukturę. Tak więc, jeśli masz coś takiego:
{
"_id": ObjectId("52b85dfa32b6249513f15897"),
"parent": "47de3176-bbc3-44e0-8063-8920ac56fdc8",
"type": "chair",
"chairtype": "E",
"content": [
{ "key": "atkswlntfd", "value": 0, "version": 0 },
{ "key": "auwbsjqzir", "value": 0, "version": 0 },
{ "key": "avqrnjzbgd", "value": 0, "version": 0 }
]
}
Lub ogólnie mniej więcej w tej formie, operacja agregacji staje się bardzo prosta:
db.collection.aggregate([
{ "$unwind": "$content" },
{ "$group": {
"_id": {
"chairtype": "$chairtype",
"key": "$content.key"
},
"average": { "$avg": "$content.value" }
}}
])
Lub jakakolwiek inna odmiana tego jest wymagana, ale teraz jest to możliwe dzięki zmianie struktury.
Więc bez innej struktury dokumentu będziesz musiał użyć mapReduce, aby to zrobić.