繁体   English   中英

比较 arrays 和过滤器,使用 MongoDB 聚合

[英]Compare arrays and filter, using MongoDB aggregation

对于我的数据库,我编写了以下管道:

let orders = await Order.aggregate(
        {
          $unwind: "$candidate",
        },
        {
          $lookup: {
            from: "groups",
            localField: "candidate.groupId",
            foreignField: "_id",
            as: "groupData",
          },
        },
        {
          $lookup: {
            from: "users",
            let: {
              id: "$candidate.groupId",
            },
            pipeline: [
              { $match: { groupId: { $ne: null } } },
              {
                $match: {
                  $expr: { $in: ["$$id", "$groupId"] },
                },
              },
              { $project: { name: 1, email: 1, _id: 1 } },
            ],
            as: "members",
          },
        },
        { $match: { "members._id": new ObjectId(req.userId) } },
        {
          $lookup: {
            from: "users",
            let: { ids: "$candidate.autonomousId" },
            pipeline: [
              {
                $match: {
                  $expr: { $in: ["$_id", "$$ids"] },
                },
              },
              { $project: { name: 1, email: 1, _id: 1 } },
            ],
            as: "candidate",
          },
        },
        {
          $project: {
            groupData: 1,
            members: 1,
            candidate: 1,
            stillAvailable: 1,
            _id: 0,
          },
        }
      ).toArray();

output 是预期的……

{ candidate:
    [ { _id: 601817dc2eeecd17db3a68f6,
        name: 'Maria' },
      { _id: 601817ef2eeecd17db3a68f7,
        name: 'Jose' } ],
   groupData:
    [ { _id: 606632403fffb851b8c41d12,
        name: 'Giraia' } ],
   members:
    [ { _id: 601817dc2eeecd17db3a68f6,
        name: 'Maria' },
      { _id: 601817ef2eeecd17db3a68f7,
        name: 'Jose' },
      { _id: 60182cbb2b654330d2458f89,
        name: 'Jonas'} ] } 

管道的最后一步是比较 arrays,过滤哪些members不是candidates成员并将它们添加到数组stillAvailable中。 我尝试了很多方法,但我无法通过聚合实现我的目标。 我能找到的唯一解决方案是在我的后端处理不完整管道的结果。 代码是:

  orders.forEach(
    (order) =>
      (order.stillAvailable = order.members.filter(
        (autonomous) =>
          !order.candidate.some((el) => {
            return el._id.toString() === autonomous._id.toString();
          })
      ))
  );

有了这个,我达到了预期的 output ......

 { candidate:
    [ { _id: 601817dc2eeecd17db3a68f6,
       name: 'Maria' },
      { _id: 601817ef2eeecd17db3a68f7,
       name: 'Jose' } ],
   groupData:
    [ { _id: 606632403fffb851b8c41d12,
        name: 'Giraia' ],
   members:
    [ { _id: 601817dc2eeecd17db3a68f6,
        name: 'Maria' },
      { _id: 601817ef2eeecd17db3a68f7,
        name: 'Jose' },
      { _id: 60182cbb2b654330d2458f89,
        name: 'Jonas' ],
   stillAvailable:
    [ { _id: 60182cbb2b654330d2458f89,
        name: 'Jonas' ] }

问题是为了更好地划分我的代码,有必要实现最后一步(在我的后端使用 javascript 完成)作为管道上的另一个步骤。 有谁知道如何达到这个目标?

在我在这里写下问题之后,不知何故,这个想法结构更好,我使用$map和更高级别的$lookup实现了结果。 我在这里留下了答案,以防有人遇到同样的问题。

  let orders = await Order.aggregate(
    {
      $unwind: "$candidate",
    },
    {
      $lookup: {
        from: "groups",
        localField: "candidate.groupId",
        foreignField: "_id",
        as: "groupData",
      },
    },
    {
      $lookup: {
        from: "users",
        let: {
          id: "$candidate.groupId",
        },
        pipeline: [
          { $match: { groupId: { $ne: null } } },
          {
            $match: {
              $expr: { $in: ["$$id", "$groupId"] },
            },
          },
          { $project: { name: 1, email: 1, _id: 1 } },
        ],
        as: "members",
      },
    },
    { $match: { "members._id": new ObjectId(req.userId) } },
    {
      $lookup: {
        from: "users",
        let: { ids: "$candidate.autonomousId" },
        pipeline: [
          {
            $match: {
              $expr: { $in: ["$_id", "$$ids"] },
            },
          },
          { $project: { name: 1, email: 1, _id: 1 } },
        ],
        as: "candidate",
      },
    },
    {
      $project: {
        groupData: 1,
        members: 1,
        candidate: 1,
        _id: 0,
        stillAvailable: {
          $setDifference: [
            {
              $map: {
                input: "$members",
                as: "member",
                in: "$$member._id",
              },
            },
            {
              $map: {
                input: "$candidate",
                as: "el",
                in: "$$el._id",
              },
            },
          ],
        },
      },
    },
    {
      $lookup: {
        from: "users",
        let: {
          ids: "$stillAvailable",
        },
        pipeline: [
          {
            $match: {
              $expr: { $in: ["$_id", "$$ids"] },
            },
          },
          { $project: { name: 1, email: 1, _id: 1 } },
        ],
        as: "stillAvailable",
      },
    }
  ).toArray();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM