Nie jest możliwe wykonanie tego typu obliczeń, które opisujesz w ramach agregacji - i to nie ponieważ nie ma $unwind
metoda dla nie-tablic. Nawet jeśli obiekty person:value były dokumentami w tablicy, $unwind
nie pomogłoby.
Funkcjonalność „grupuj według” (czy to w MongoDB, czy w dowolnej relacyjnej bazie danych) jest wykonywana na wartości pola lub kolumny. Grupujemy według wartości pola i sumy/średniej/itd. na podstawie wartości innego pola.
Prosty przykład to wariant tego, co sugerujesz, pole ocen dodane do przykładowej kolekcji artykułów, ale nie jako mapa od użytkownika do oceny, ale jako tablica:
{ title : title of article", ...
ratings: [
{ voter: "user1", score: 5 },
{ voter: "user2", score: 8 },
{ voter: "user3", score: 7 }
]
}
Teraz możesz to zagregować za pomocą:
[ {$unwind: "$ratings"},
{$group : {_id : "$ratings.voter", averageScore: {$avg:"$ratings.score"} } }
]
Ale ten przykład skonstruowany tak, jak go opisujesz, wyglądałby tak:
{ title : title of article", ...
ratings: {
user1: 5,
user2: 8,
user3: 7
}
}
a nawet to:
{ title : title of article", ...
ratings: [
{ user1: 5 },
{ user2: 8 },
{ user3: 7 }
]
}
Nawet gdybyś mógł $unwind
tutaj nie ma się czego agregować. Jeśli nie znasz pełnej listy wszystkich możliwych kluczy (użytkowników), niewiele możesz z tym zrobić. [*]
Analogiczny schemat relacyjnej bazy danych do tego, który masz, to:
CREATE TABLE T (
user1: integer,
user2: integer,
user3: integer
...
);
Nie zrobilibyśmy tego, zamiast tego zrobilibyśmy to:
CREATE TABLE T (
username: varchar(32),
score: integer
);
a teraz agregujemy za pomocą SQL:
select username, avg(score) from T group by username;
Istnieje prośba o ulepszenie MongoDB, która może pozwolić na zrobienie tego w przyszłości w ramach agregacji — możliwość rzutowania wartości na klucze na odwrót. Tymczasem zawsze jest mapa/redukcja.
[*] Jest to skomplikowany sposób, jeśli znasz wszystkie unikalne klucze (możesz znaleźć wszystkie unikalne klucze za pomocą metody podobnej do tej), ale jeśli znasz wszystkie klucze, możesz równie dobrze uruchomić sekwencję zapytań formularz db.articles.find({"ratings.user1":{$exists:true}},{_id:0,"ratings.user1":1})
dla każdego użytkownika X, który zwróci wszystkie jego oceny i możesz je zsumować i uśrednić, zamiast wykonywać bardzo złożone prognozy, których wymagałaby struktura agregacji.