Mongo 项目添加到数组

Mongo project add to array

我正在尝试将一个项目添加到聚合数组中,但似乎坚持了几天。 这是它的样子:

db={
  Students: [
    {
      "id": "123",
      "title": "John",
      "marks_in_subjects": [
        {
          "marks": 90,
          "subject_id": "abc"
        },
        {
          "marks": 92,
          "subject_id": "def"
        }
      ]
    }
  ],
  Subjects: [
    {
      "id": "abc",
      "name": "math"
    },
    {
      "id": "def",
      "name": "physics"
    }
  ]
}

然后我像这样将项目和标题连接到新字段:

db.Students.aggregate([
  {
    $unwind: "$marks_in_subjects"
  },
  {
    "$lookup": {
      "from": "Subjects",
      "localField": "marks_in_subjects.subject_id",
      "foreignField": "id",
      "as": "subjects"
    }
  },
  {
    $unwind: "$subjects"
  },
  {
    $project: {
      _id: "$_id",
      title: "$title",
      titleAll: {
        $concat: [
          "$title",
          " > ",
          "$subjects.name",
          
        ]
      },
      
    }
  },
  
])

这是我得到的输出:

[
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "title": "John",
    "titleAll": "John \u003e math"
  },
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "title": "John",
    "titleAll": "John \u003e physics"
  }
]

现在,我希望我的输出包含数组中的第一项,只有真正的标题,然后列出所有这些,如下所示:

[
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "title": "John",
    "titleAll": "John"
  },
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "title": "John",
    "titleAll": "John \u003e math"
  },
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "title": "John",
    "titleAll": "John \u003e physics"
  }
]

有什么办法可以实现吗?我尝试使用 $cond,但似乎不起作用。 这是 link 到 Mongo playground

  1. $unwind
  2. $lookup
  3. $group - 按 _id 分组。获取 title 字段和 subjects 数组(阶段 4 需要此字段)。
  4. $set - 通过在 subjects.
  5. 中添加第一个文档和现有文档来修改 subjects 字段
  6. $unwind - 解构 subjects 字段。
  7. $project - 修饰输出文档。
db.Students.aggregate([
  {
    $unwind: "$marks_in_subjects"
  },
  {
    "$lookup": {
      "from": "Subjects",
      "localField": "marks_in_subjects.subject_id",
      "foreignField": "id",
      "as": "subjects"
    }
  },
  {
    $group: {
      _id: "$id",
      title: {
        $first: "$title"
      },
      subjects: {
        $push: {
          $first: "$subjects"
        }
      }
    }
  },
  {
    $set: {
      subjects: {
        $concatArrays: [
          [
            {
              titleAll: "$title"
            }
          ],
          {
            $map: {
              input: "$subjects",
              in: {
                titleAll: {
                  $concat: [
                    "$title",
                    " > ",
                    "$$this.name"
                  ]
                }
              }
            }
          }
        ]
      }
    }
  },
  {
    $unwind: "$subjects"
  },
  {
    $project: {
      _id: 1,
      title: 1,
      titleAll: "$subjects.titleAll"
    }
  }
])

Sample Mongo Playground

你可以用更简单的方法来做:

无需再次 $unwind$group。缺少的步骤是将 title 连接到 titleAll 数组。

db.Students.aggregate([
  {
    $lookup: {
      from: "Subjects",
      localField: "marks_in_subjects.subject_id",
      foreignField: "id",
      as: "subjects"
    }
  },
  {
    $project: {subjects: "$subjects.name", title: 1}
  },
  {
    $addFields: {
      titleAll: {
        $map: {
          input: "$subjects",
          as: "item",
          in: {$concat: ["$title", " > ", "$$item"]}
        }
      }
    }
  },
  {
    $project: {
      title: "$title",
      titleAll: {"$concatArrays": ["$titleAll", ["$title"]]}
    }
  },
  {
    $unwind: "$titleAll"
  }
])

Sample MongoDB Playground