Typ výpočtu, který popisujete, není možné provést pomocí agregačního rámce – a není protože neexistuje žádný $unwind
metoda pro non-pole. I když objekty person:value byly dokumenty v poli, $unwind
by nepomohlo.
Funkce "seskupit podle" (ať už v MongoDB nebo v jakékoli relační databázi) se provádí na hodnotě pole nebo sloupce. Seskupujeme podle hodnoty pole a součtu/průměru/atd. na základě hodnoty jiného pole.
Jednoduchý příklad je varianta toho, co navrhujete, pole hodnocení přidané do vzorové kolekce článků, ale ne jako mapa od uživatele k hodnocení, ale jako pole, jako je toto:
{ title : title of article", ...
ratings: [
{ voter: "user1", score: 5 },
{ voter: "user2", score: 8 },
{ voter: "user3", score: 7 }
]
}
Nyní to můžete agregovat pomocí:
[ {$unwind: "$ratings"},
{$group : {_id : "$ratings.voter", averageScore: {$avg:"$ratings.score"} } }
]
Ale tento příklad strukturovaný tak, jak popisujete, by vypadal takto:
{ title : title of article", ...
ratings: {
user1: 5,
user2: 8,
user3: 7
}
}
nebo dokonce toto:
{ title : title of article", ...
ratings: [
{ user1: 5 },
{ user2: 8 },
{ user3: 7 }
]
}
I kdybyste mohli $unwind
tady není co agregovat. Pokud neznáte úplný seznam všech možných klíčů (uživatelů), nemůžete s tím mnoho dělat. [*]
Analogické schéma relační databáze k tomu, co máte, by bylo:
CREATE TABLE T (
user1: integer,
user2: integer,
user3: integer
...
);
To není to, co by se udělalo, místo toho bychom udělali toto:
CREATE TABLE T (
username: varchar(32),
score: integer
);
a nyní agregujeme pomocí SQL:
select username, avg(score) from T group by username;
Existuje požadavek na vylepšení pro MongoDB, který vám to může v budoucnu umožnit v agregačním rámci – možnost promítat hodnoty do klíčů a naopak. Mezitím vždy existuje mapa/zmenšení.
[*] Existuje složitý způsob, jak to udělat, pokud znáte všechny jedinečné klíče (všechny jedinečné klíče můžete najít pomocí metody podobné této), ale pokud znáte všechny klíče, můžete také spustit sekvenci dotazů formulář db.articles.find({"ratings.user1":{$exists:true}},{_id:0,"ratings.user1":1})
pro každého uživateleX, který vrátí všechna jeho hodnocení a můžete je sečíst a zprůměrovat dostatečně jednoduše, místo abyste prováděli velmi složitou projekci, kterou by agregační rámec vyžadoval.