首页 > 解决方案 > 通过检查数组 Mongodb 中的值从双重嵌套数组中进行投影

问题描述

{
    _id: 'uniquewId',
    programs: [
        {
            prgName: 'prgOne',
            progress: '5',
            addedBy: 'coach'
            exercises: [
                {
                     date: '1/12/20',
                     exercises: [
                         {
                              exId: 'pushup',
                              progress: 5,
                              attributes: [
                                  {
                                     id: 'myId',
                                     done: true
                                  },
                                  {
                                     id: 'myId2',
                                     done: false
                                  } 
                              ]
                         },
                         {
                              exId: 'situp',
                              progress: 5,
                              attributes: [
                                  {
                                     id: 'myId',
                                     done: true
                                  },
                                  {
                                     id: 'myId2',
                                     done: true
                                  } 
                              ]
                         }
                     ] 
                },
                {
                    date: '2/12/20',
                    exercises: [
                         {
                              exId: 'pushup',
                              progress: 5,
                              attributes: [
                                  {
                                     id: 'myId',
                                     done: true
                                  },
                                  {
                                     id: 'myId2',
                                     done: false
                                  } 
                              ]
                         },
                         {
                              exId: 'situp',
                              progress: 5,
                              attributes: [
                                  {
                                     id: 'myId',
                                     done: fase
                                  },
                                  {
                                     id: 'myId2',
                                     done: false
                                  } 
                              ]
                         }
                     ] 
                }   
            ]
        },
        {
            prgName: 'prgTwo',
            progress: '5',
            addedBy: 'coach2'
            exercises: [
                 {
                     date: '1/12/20',
                     exercises: [
                         {
                              exId: 'pushup',
                              progress: 5,
                              attributes: [
                                  {
                                     id: 'myId',
                                     done: true
                                  },
                                  {
                                     id: 'myId2',
                                     done: true
                                  } 
                              ]
                         },
                         {
                              exId: 'situp',
                              progress: 5,
                              attributes: [
                                  {
                                     id: 'myId',
                                     done: false
                                  },
                                  {
                                     id: 'myId2',
                                     done: false
                                  } 
                              ]
                         }
                     ] 
                },
                {
                    date: '2/12/20',
                    exercises: [
                         {
                              exId: 'pushup',
                              progress: 5,
                              attributes: [
                                  {
                                     id: 'myId',
                                     done: true
                                  },
                                  {
                                     id: 'myId2',
                                     done: false
                                  } 
                              ]
                         },
                         {
                              exId: 'situp',
                              progress: 5,
                              attributes: [
                                  {
                                     id: 'myId',
                                     done: true
                                  },
                                  {
                                     id: 'myId2',
                                     done: false
                                  } 
                              ]
                         }
                     ] 
                }   
            ]
        }
    ]
}

以上是我的文档的结构。我想要做的是从程序数组中投影出练习的名称,这些练习的名称在属性数组中至少有一个文档,该文档已将键标记为真。我想要做的是找出在属性数组中设置为 true 的练习
有什么办法可以得到如下输出:

{
    _id: 'uniquewId',
    programs: [
        {
            prgName: 'prgOne',
            exercises: [
                'pushup',
                'situp'  
            ]  
        },
        {
            prgName: 'prgTwo',
            exercises: [
                'pushup',
                'situp'  
            ]  
        }
    ]
}

标签: node.jsmongodbaggregation-framework

解决方案


这是一个乏味的过程

使用$map运算符,我们可以遍历数组。还$map允许将对象数组转换为字符串数组。

[{k1:v1}, {k2:v2}, ...] -> [v1, v2, ...]

伪代码

第一步。我们执行复杂的聚合并预先计算值

for (Programs program: doc.programs) {
    return {
        prgName : program.prgName,
        exercises : [
            for (Exercises exer1: program.exercises) {
                for (Exercises exer2: exer1.exercises) {
                    return {
                        exId : exer2.exId,
                        done : exer2.attributes.done.contains(true)
                    }
                }
            }
        ]
    }
}

第二步。我们构建期望的结果


db.collection.aggregate([
  {
    $project: {
      programs: {
        $map: {
          input: "$programs",
          as: "program",
          in: {
            prgName: "$$program.prgName",
            exercises: {
              $reduce: {
                input: {
                  $map: {
                    input: "$$program.exercises",
                    as: "exer1",
                    in: {
                      $map: {
                        input: "$$exer1.exercises",
                        as: "exer2",
                        in: {
                          exId: "$$exer2.exId",
                          done: {
                            $in: [
                              true,
                              "$$exer2.attributes.done"
                            ]
                          }
                        }
                      }
                    }
                  }
                },
                initialValue: [],
                in: {
                  $concatArrays: [
                    "$$value",
                    "$$this"
                  ]
                }
              }
            }
          }
        }
      }
    }
  },
  {
    $project: {
      programs: {
        $map: {
          input: "$programs",
          as: "program",
          in: {
            prgName: "$$program.prgName",
            exercises: {
              $reduce: {
                input: {
                  $filter: {
                    input: "$$program.exercises",
                    cond: {
                      $eq: [
                        "$$this.done",
                        true
                      ]
                    }
                  }
                },
                initialValue: [],
                in: {
                  $concatArrays: [
                    "$$value",
                    {
                      $cond: [
                        {
                          $in: [
                            "$$this.exId",
                            "$$value"
                          ]
                        },
                        [],
                        [
                          "$$this.exId"
                        ]
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    }
  }
])

Mongo游乐场


推荐阅读