Struktura dat zde není dobrá implementace, existuje mnoho problémů s tím, jak je strukturována, a je zcela nevhodná pro agregaci. Hlavní problémy zde jsou:
-
Vaše struktura ve skutečnosti nepoužívá žádná pole, právě teď ne
-
Všechny konkrétní názvy klíčů představují skutečný problém a tomu se lze vyhnout.
Jediným způsobem, jak procházet touto strukturou, je použití JavaScriptu s mapReduce.
Definování mapovače:
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]
);
}
}
};
Takže to, co dělá, je cyklické procházení jednotlivých položek verzí a pak také vše, co se týká obsahu. Klíč je vydáván pro každý z požadovaných obsahových klíčů a také pomocí klíče „typ židle“. A hodnota je ta odpovídající hodnota.
A pak redukce:
var reducer = function (key,values) {
return ( Array.sum( values ) != 0 )
? Array.sum( values ) / values.length : 0;
};
Což je jen jednoduchý způsob, jak vytvořit průměr ze všech hodnot přicházejících do mapovače se stejným klíčem.
Takže i když by to mělo fungovat dobře, měli byste změnit svou strukturu. Takže ve skutečnosti, pokud jste měli něco takového:
{
"_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 }
]
}
Nebo obecně víceméně v této podobě se operace agregace stává velmi jednoduchou:
db.collection.aggregate([
{ "$unwind": "$content" },
{ "$group": {
"_id": {
"chairtype": "$chairtype",
"key": "$content.key"
},
"average": { "$avg": "$content.value" }
}}
])
Nebo jakákoli jiná varianta tohoto je vyžadována, ale nyní je to možné díky změně struktury.
Takže aniž by byl dokument jinak strukturován, budete k tomu muset použít mapReduce.