Не е възможно да направите типа изчисление, който описвате с рамката за агрегиране - и това е не защото няма $unwind
метод за немасиви. Дори ако обектите person:value са документи в масив, $unwind
няма да помогне.
Функцията "групиране по" (независимо дали в MongoDB или в която и да е релационна база данни) се извършва върху стойността на поле или колона. Групираме по стойност на полето и сума/средна стойност/и т.н. въз основа на стойността на друго поле.
Прост пример е вариант на това, което предлагате, поле за оценки е добавено към примерната колекция от статии, но не като карта от потребител към оценка, а като масив като този:
{ title : title of article", ...
ratings: [
{ voter: "user1", score: 5 },
{ voter: "user2", score: 8 },
{ voter: "user3", score: 7 }
]
}
Сега можете да обобщите това с:
[ {$unwind: "$ratings"},
{$group : {_id : "$ratings.voter", averageScore: {$avg:"$ratings.score"} } }
]
Но този пример, структуриран както го описвате, би изглеждал така:
{ title : title of article", ...
ratings: {
user1: 5,
user2: 8,
user3: 7
}
}
или дори това:
{ title : title of article", ...
ratings: [
{ user1: 5 },
{ user2: 8 },
{ user3: 7 }
]
}
Дори ако можете да $unwind
това, тук няма какво да се обобщава. Освен ако не знаете пълния списък на всички възможни ключове (потребители), не можете да направите много с това. [*]
Аналогична релационна DB схема на това, което имате, би била:
CREATE TABLE T (
user1: integer,
user2: integer,
user3: integer
...
);
Не това ще бъде направено, вместо това ще направим това:
CREATE TABLE T (
username: varchar(32),
score: integer
);
и сега агрегираме с помощта на SQL:
select username, avg(score) from T group by username;
Има заявка за подобрение за MongoDB, която може да ви позволи да правите това в рамката за агрегиране в бъдеще - възможността да проектирате стойности към ключове и обратно. Междувременно винаги има карта/намаляване.
[*] Има сложен начин да направите това, ако знаете всички уникални ключове (можете да намерите всички уникални ключове с метод, подобен на този), но ако знаете всички ключове, можете също така просто да изпълните поредица от заявки на форма db.articles.find({"ratings.user1":{$exists:true}},{_id:0,"ratings.user1":1})
за всеки userX, който ще върне всичките им оценки и можете да ги сумирате и осредните достатъчно просто, вместо да правите много сложна проекция, която рамката за агрегиране ще изисква.