#mongodb #aggregate #pipeline
#mongodb #агрегат #конвейер
Вопрос:
Я использовал коллекцию опросов и $ lookup, чтобы найти связанные ответы на вопросы опроса.
Теперь я хочу ввести user_oid и создать «user_answer_count», используя $addField.
Код:
Survey.aggregate([
{ $match: { team_oid: mongoose.Types.ObjectId(req.params.t_oid) } },
{ $addFields: { count_questions: { $size: "$questions"} } },
{ $unwind: { path: "$questions" } },
{ $lookup: { from: 'answers', localField: 'questions', foreignField: 'question_oid', as: 'answer' } },
{ $unwind: { path: "$answer", preserveNullAndEmptyArrays: true } },
{ $addFields: {
answer_count: { $cond: [{ $eq: [{ $type: "$answer" }, "object" ]}, 1, 0] } },
user_answer_count: { $cond: [{ $eq: ["$answer.user_oid", mongoose.Types.ObjectId(req.params.u_oid) ]}, 1, 0] }
},
{ $lookup: { from: 'votes', localField: '_id', foreignField: 'surveyOid', as: 'votes' } },
{ $unwind: { path: "$votes", preserveNullAndEmptyArrays: true } },
{ $addFields: { vote_count: { $cond: [{ $eq: [{ $type: "$votes" }, "object"] }, 0.2, 0] } } },
{
$group: {
_id: "$_id",
huddle_number: { $first: "$huddle_number" },
count_questions: { $first: "$count_questions" },
count_answers: { $sum: "$answer_count" },
count_votes: { $sum: "$vote_count" },
count_user_answers: { $sum: "$user_answer_count" },
sefirot_state: { $first: "$sefirot_state" },
created_date: { $first: "$created_date" },
avg_positive: { $avg: "$answer.positive" },
avg_creative: { $avg: "$answer.creative" },
avg_focused: { $avg: "$answer.focused" },
avg_friendly: { $avg: "$answer.friendly" },
avg_aligned: { $avg: "$answer.aligned" },
avg_alert: { $avg: "$answer.alert" }
}
}
]).exec((err, doc) => {
Здесь все работает, первое $ addField «answer_count» работает отлично. Но второй, «user_answer_count», полностью завершает работу.
Консоль сообщает: Arguments must be aggregate pipeline operators
Это моя первая попытка использовать $lookup с $ addFields, поэтому предложения приветствуются!
Редактировать:
Примеры документов
**Survey**
_id : 5f5a372d9ea9981e7c5773cb
questions :
0 : 5f522b025dd8993e58283522
1 : 5f47a892db023557105e2be3
2 : 5f522a9d5dd8993e58283520
3 : 5f0e23ef2e0fcb3fe04a7314
4 : 5f522b285dd8993e58283523
created_date : 2020-09-10T14:24:45.439 00:00
team_oid : 5f44cc20c74f8a444851d9c2
huddle_number : 22
sefirot_state : "Aligned"
__v : 0
**Answer**
_id : 5f58bb04772a5943a0b54ec9
question : "What does "winning" look like in this team?"
question_oid : 5f522bc55dd8993e58283526
user_team_oid : 5f44cc20c74f8a444851d9c2
user_oid : 5f1ef3e8accff82f3cae3957
comment : "It means Cobra Kai Never Die and Only Get Better"
created_date : 2020-09-09T11:22:44.098 00:00
__v : 0
Комментарии:
1. Спасибо @turivishal — я попробовал это, но получил ту же ошибку…
Ответ №1:
Есть несколько исправлений, пропущенные скобки и $cond
неправильный синтаксис, также этот способ неверен для получения количества массивов.
- подсчитайте количество элементов в используемом массиве
$size
, дляanswer_count
- вы можете использовать
$reduce
оператор массива для подсчета количества пользователей, нет необходимости использовать$unwind
массив ответов
{ $lookup: { ... } }, // skipping
{
$addFields: {
answer_count: { $size: "$answer" },
user_answer_count: {
$reduce: {
input: "$answer",
initialValue: 0,
in: {
$cond: [
{ $eq: ["$$this.user_oid", mongoose.Types.ObjectId(req.params.u_oid)] },
{ $add: ["$$value", 1] },
"$$value"
]
}
}
}
}
}
Комментарии:
1. Спасибо @turivishal. Это полезный ответ, и он работает хорошо, однако он не работает, когда я применяю его к своему коду. Я думаю, поскольку я выполняю предыдущие операции в
aggregate
методе, данные уже структурированы? Я добавил остальную часть агрегации в свой вопрос, если вы хотите взглянуть. Я пытаюсь решить это со своей стороны. Еще раз спасибо, если я смогу выполнить эту работу, я приму этот ответ.2. Хорошо, предоставьте некоторые документы для другой коллекции также в playground, поэтому я рассмотрю это