Агрегат MongoDB, $ addFields не работает с $ cond

#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, поэтому я рассмотрю это