Проект двойного вложенного массива mongodb - PullRequest
1 голос
/ 26 марта 2020
{
    _id: 'uniquewId',
    programs: [
        {
            progress: '5',
            addedBy: 'coach'
            exercises: [
                {
                     date: '1/12/20',
                     exercises: [
                         {
                              exId: 'pushup',
                              progress: 5
                         },
                         {
                              exId: 'situp',
                              progress: 5
                         },
                         {
                              exId: 'pushup',
                              progress: 0
                         }
                     ] 
                },
                {
                    date: '2/12/20',
                     exercises: [
                         {
                              exId: 'pushup',
                              progress: 5
                         },
                         {
                              exId: 'situp',
                              progress: 5
                         },
                         {
                              exId: 'pushup',
                              progress: 0
                         }
                     ] 
                }   
            ]
        },
        {
            progress: '5',
            addedBy: 'coach2'
            exercises: [
                {
                     date: '1/12/20',
                     exercises: [
                         {
                              exId: 'pushup',
                              progress: 5
                         },
                         {
                              exId: 'situp',
                              progress: 5
                         },
                         {
                              exId: 'pushup',
                              progress: 0
                         }
                     ] 
                },
                {
                    date: '2/12/20',
                     exercises: [
                         {
                              exId: 'pushup',
                              progress: 5
                         },
                         {
                              exId: 'situp',
                              progress: 5
                         },
                         {
                              exId: 'pushup',
                              progress: 0
                         }
                     ] 
                }   
            ]
        }
    ]
}

Это выше, как выглядит мой документ. Есть ли способ, которым я могу проецировать массив программ, чтобы он имел документы, которые имеют addedBy = 'coach', а массив упражнений внутри массива упражнений должен иметь только exId = 'pushup'

вывод, который я хочу:

{
    _id: 'uniquewId',
    programs: [
        {
            progress: '5',
            addedBy: 'coach'
            exercises: [
                {
                     date: '1/12/20',
                     exercises: [
                         {
                              exId: 'pushup',
                              progress: 5
                         },
                         {
                              exId: 'pushup',
                              progress: 0
                         }
                     ] 
                },
                {
                    date: '2/12/20',
                     exercises: [
                         {
                              exId: 'pushup',
                              progress: 5
                         },
                         {
                              exId: 'pushup',
                              progress: 0
                         }
                     ] 
                }   
            ]
        }
    ]
}

программный массив может иметь более одного документа с addedBy='coach', если так, то все должно быть там:)

Ответы [ 2 ]

1 голос
/ 26 марта 2020

Я не думаю, что одна проекция может помочь вам достичь описанного вами результата. Попробуйте это:

db.collection.aggregate([
  {
    $unwind: "$programs"
  },
  {
    $match: {
      "programs.addedBy": "coach"
    }
  },
  {
    $project: {
      programs: {
        progress: "$programs.progress",
        addedBy: "$programs.addedBy",
        exercises: {
          $map: {
            input: "$programs.exercises",
            as: "exercise",
            in: {
              date: "$$exercise.date",
              exercises: {
                $filter: {
                  input: "$$exercise.exercises",
                  as: "exerciseDetails",
                  cond: {
                    $eq: [
                      "$$exerciseDetails.exId",
                      "pushup"
                    ]
                  }
                }
              }
            }
          },

        }
      }
    }
  },
  {
    $group: {
      _id: "$_id",
      programs: {
        $push: "$programs"
      }
    }
  }
])

Почему это должно работать:

Выше приведена агрегация для получения описанного вывода. Я использую 4 этапа агрегации и пару операторов агрегации в конвейере. Этапы:

  • $ unwind - Это помогает распределить массив программ таким образом, чтобы у меня было по одному документу на программу, что позволяет легко работать с вложенным массивом упражнений внутри каждого программа.
  • $ match - это помогает отфильтровать программы, не добавленные "coach"
  • $ project - Это в основном проецирует данные вперед при применении преобразование с использованием операторов агрегирования для некоторых входных данных. Я использовал оператор $ map в "program.exercises", чтобы получить доступ к каждому упражнению в массиве упражнений. В каждом объекте упражнения я использовал оператор $ filter в массиве вложенных упражнений для удаления упражнений, для которых exId не является «pushup».
  • $ group - Это просто очистка от $ unwind, которую я делал ранее, группирует программы, которые я распространял в начале конвейера.

Вы можете проверить это на этой детской площадке

1 голос
/ 26 марта 2020

Двойной $ map и двойной $ filter сделают свое дело:

db.collection.aggregate([
    {
        $project: {
            _id: 1,
            programs: {
                $map: {
                    input: { $filter: { input: "$programs", cond: { $eq: [ "$$this.addedBy", "coach" ] } } },
                    in: {
                        progress: "$$this.progress",
                        addedBy: "$$this.addedBy",
                        exercises: {
                            $map: {
                                input: "$$this.exercises",
                                in: {
                                    date: "$$this.date",
                                    exercises: {
                                        $filter: {
                                            input: "$$this.exercises",
                                            as: "e",
                                            cond: {
                                                $eq: [ "$$e.exId", "pushup" ]
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
])

Пн go Детская площадка

...