Вы можете использовать структуру агрегации для расчета агрегатов. Это более быстрая альтернатива Map/Reduce для общих операций агрегации. В MongoDB конвейер состоит из серии специальных операторов, применяемых к коллекции для обработки записей данных и возврата вычисленных результатов. Агрегация операций группирует значения из нескольких документов вместе и может выполнять множество операций над сгруппированными данными, чтобы вернуть один результат. Для получения дополнительной информации обратитесь к documentation.
Считайте, выполнив следующий трубопровод, чтобы получить желаемый результат:
var pipeline = [
{ "$unwind": "$userPicks" },
{
"$group": {
"_id": {
"week": "$week",
"user": "$userPicks.user"
},
"weeklyScore": {
"$sum": {
"$cond": [
{ "$eq": ["$userPicks.chosenTeam", "$winner"] },
1, 0
]
}
}
}
},
{
"$group": {
"_id": "$_id.user",
"weeklyScores": {
"$push": {
"week": "$_id.week",
"score": "$weeklyScore"
}
},
"totalScores": { "$sum": "$weeklyScore" }
}
}
];
Game.aggregate(pipeline, function(err, results){
User.populate(results, { "path": "_id" }, function(err, results) {
if (err) throw err;
console.log(JSON.stringify(results, undefined, 4));
});
})
В вышеуказанном трубопроводе, первый шаг является $unwind
оператор
{ "$unwind": "$userPicks" }
, который поставляется в довольно когда данные хранятся в виде массива. Когда оператор разматывания применяется в поле данных списка, он будет генерировать новую запись для каждого элемента поля данных списка, на котором выполняется размотка. Это в основном сглаживает данные.
Это необходимая операция для следующего этапа трубопровода, этап $group
, где группа уплощенных документов по полям week
и "userPicks.user"
{
"$group": {
"_id": {
"week": "$week",
"user": "$userPicks.user"
},
"weeklyScore": {
"$sum": {
"$cond": [
{ "$eq": ["$userPicks.chosenTeam", "$winner"] },
1, 0
]
}
}
}
}
Оператор конвейер $group
похож на Предложение SQL GROUP BY
. В SQL вы не можете использовать GROUP BY
, если не используете какие-либо функции агрегации. Точно так же вы должны использовать функцию агрегации в MongoDB. Подробнее о функциях агрегации вы можете узнать here.
В этом $group
операции, логика для расчета еженедельной счет каждого пользователя (то есть количество футбольных игр они предсказывают правильно каждую неделю) осуществляется через тройной оператор $cond
, который принимает логическое условие, поскольку это первый аргумент (if), а затем возвращает второй аргумент, где оценка истинна (тогда) или третий аргумент, где false (else). Это делает истина/ложь возвращается в 1 и 0, чтобы питаться $sum
соответственно:
"$cond": [
{ "$eq": ["$userPicks.chosenTeam", "$winner"] },
1, 0
]
Так, если в документе, который обработал "$userPicks.chosenTeam"
поле такое же, как "$winner"
поле, $cond
оператор кормами значение 1 в сумму иначе оно суммирует нулевое значение.
Вторые группа трубопроводы:
{
"$group": {
"_id": "$user",
"weeklyScores": {
"$push": {
"week": "$_id.week",
"score": "$weeklyScore"
}
},
"totalScores": { "$sum": "$weeklyScore" }
}
}
принимают документы из предыдущего трубопровода и групп их далее по user
полю и вычисляют другую совокупность т.е. общего балла, используя оператор аккумулятора в $sum
. В рамках одного и того же конвейера вы можете агрегировать список недельных оценок с помощью оператора $push
, который возвращает массив значений выражений для каждой группы.
Следует отметить, что при выполнении трубопровода MongoDB соединяет операторы друг с другом. «Pipe» здесь означает значение Linux: выход оператора становится входом следующего оператора. Результатом каждого оператора является новая коллекция документов. Так Монго выполняет выше трубопровод следующим образом:
collection | $unwind | $group | $group => result
Теперь при запуске трубопровода агрегации в Mongoose, результаты будут иметь _id
ключ, который является идентификатором пользователя, и вам необходимо заполнить результаты на этом поле, т.е. Mongoose будет выполнять «соединение» с коллекцией пользователей и возвращать документы с пользовательской схемой в результатах.
В качестве примечания, чтобы помочь с пониманием трубопровода или отлаживать его вы должны получить неожиданные результаты, запустить агрегацию только с первым оператором трубопровода. Например, запустить агрегация в Монго оболочки, как:
db.games.aggregate([
{ "$unwind": "$userPicks" }
])
Проверьте результат, чтобы увидеть, если userPicks
массив деконструкции правильно. Если это дает ожидаемый результат, добавьте следующий:
db.games.aggregate([
{ "$unwind": "$userPicks" },
{
"$group": {
"_id": {
"week": "$week",
"user": "$userPicks.user"
},
"weeklyScore": {
"$sum": {
"$cond": [
{ "$eq": ["$userPicks.chosenTeam", "$winner"] },
1, 0
]
}
}
}
}
])
Повторите шаги, пока вы получите до конечной стадии трубопровода.
привет, эта часть машинного обучения? как вы хотите рассчитать домашний счет? это прирост от предыдущего балла? – vdj4y