Non è possibile eseguire il tipo di calcolo che stai descrivendo con il framework di aggregazione e non perché non c'è $unwind
metodo per non array. Anche se gli oggetti persona:valore fossero documenti in un array, $unwind
non sarebbe d'aiuto.
La funzionalità "raggruppa per" (sia in MongoDB che in qualsiasi database relazionale) viene eseguita sul valore di un campo o di una colonna. Raggruppiamo per valore di campo e somma/media/ecc in base al valore di un altro campo.
Un semplice esempio è una variante di ciò che suggerisci, il campo delle valutazioni è stato aggiunto alla raccolta di articoli di esempio, ma non come una mappa dall'utente alla valutazione, ma come una matrice come questa:
{ title : title of article", ...
ratings: [
{ voter: "user1", score: 5 },
{ voter: "user2", score: 8 },
{ voter: "user3", score: 7 }
]
}
Ora puoi aggregarlo con:
[ {$unwind: "$ratings"},
{$group : {_id : "$ratings.voter", averageScore: {$avg:"$ratings.score"} } }
]
Ma questo esempio strutturato come lo descrivi sarebbe simile a questo:
{ title : title of article", ...
ratings: {
user1: 5,
user2: 8,
user3: 7
}
}
o anche questo:
{ title : title of article", ...
ratings: [
{ user1: 5 },
{ user2: 8 },
{ user3: 7 }
]
}
Anche se potessi $unwind
questo, non c'è niente su cui aggregare qui. A meno che tu non conosca l'elenco completo di tutte le possibili chiavi (utenti), non puoi fare molto con questo. [*]
Uno schema DB relazionale analogo a quello che hai sarebbe:
CREATE TABLE T (
user1: integer,
user2: integer,
user3: integer
...
);
Non è quello che si fa, invece si fa così:
CREATE TABLE T (
username: varchar(32),
score: integer
);
e ora aggreghiamo usando SQL:
select username, avg(score) from T group by username;
Esiste una richiesta di miglioramento per MongoDB che potrebbe consentirti di farlo nel framework di aggregazione in futuro:la possibilità di proiettare valori su chiavi e viceversa. Nel frattempo, c'è sempre mappa/riduci.
[*] C'è un modo complicato per farlo se conosci tutte le chiavi univoche (puoi trovare tutte le chiavi univoche con un metodo simile a questo) ma se conosci tutte le chiavi puoi anche eseguire una sequenza di query del form db.articles.find({"ratings.user1":{$exists:true}},{_id:0,"ratings.user1":1})
per ogni utenteX che restituirà tutte le sue valutazioni e puoi sommarle e fare una media abbastanza semplicemente piuttosto che fare una proiezione molto complessa che il framework di aggregazione richiederebbe.