使用mongoose node js的级联连接

Cascaded join using mongoose node js

我正在尝试使用 Node Js 从 MongoDB 获取数据。我有三个模式:项目、用户和团队。 我需要检索 项目详细信息,基于 type 工作用户 。 我在为这些模式制作 join 时陷入困境:

项目:

const Project = new Schema({
    projectName: { type: String, required: true, trim: true },
    type: { type: String, required: true, trim: true },
    teamID: { type: Schema.Types.ObjectId, required: true },
});

团队

const Team = new Schema({
    teamId: { type: Schema.Types.ObjectId, required: true, trim: true },
    users: { type: [Schema.Types.ObjectId], required: true, trim: true },
    teamName: { type: String, required: true },
});

用户:

const User = new Schema({
    userId: { type: Schema.Types.ObjectId, required: true, trim: true },
    name: { type: String, required: true, trim: true },
    profilePicture: { type: String, required: true, trim: true },
});

我正在想办法得到

[
   {
      projectName: "s",
      type: "w",
      users: ["Jon", "Ali", "Mark"]
   },
   {
      projectName: "a",
      type: "w",
      users: ["Jon", "Mark"]
   },   {
      projectName: "s",
      type: "w",
      users: ["Jon", "Ali", "Mark"]
   },
]

我尝试使用$lookup,但我不能使用它,因为关系是复杂的多对多关系。 有没有比检索所有用户、所有团队和所有项目更有效的方法?

我认为除了聚合没有其他有效的方法,没有查找我们不能加入集合,你可以使用嵌套查找,

  • $match type
  • 的条件
  • $lookup 使用 teamID
  • 加入团队合集
  • $match teamID
  • $lookup 使用 users 数组加入用户集合
  • $project 使用 $map
  • 转换用户名数组
  • $addFields 使用 $arrayElemAt
  • 在用户中获取用户数组
db.Project.aggregate([
  { $match: { type: "w" } },
  {
    $lookup: {
      from: "Team",
      let: { teamID: "$teamID" },
      as: "users",
      pipeline: [
        { $match: { $expr: { $eq: ["$$teamID", "$teamId"] } } },
        {
          $lookup: {
            from: "User",
            localField: "users",
            foreignField: "userId",
            as: "users"
          }
        },
        {
          $project: {
            users: {
              $map: {
                input: "$users",
                in: "$$this.name"
              }
            }
          }
        }
      ]
    }
  },
  { $addFields: { users: { $arrayElemAt: ["$users.users", 0] } } }
])

Playground


第二种可能的方法,您可以将 $project$addFields 个阶段合并为一个阶段,

  {
    $addFields: {
      users: {
        $arrayElemAt: [
          {
            $map: {
              input: "$users.users",
              in: "$$this.name"
            }
          },
          0
        ]
      }
    }
  }

Playground