javascript MongoDB -如何将集合子数组对象与其他集合中的实际对象聚合

0md85ypi  于 2023-06-04  发布在  Java
关注(0)|答案(2)|浏览(129)

如何聚合集合子数组对象与它们在另一个集合中的实际对象?

  • 这就是我收藏的样子 *
    集合1 -(团队)
const Teams = [
    {
        _id: '60f3b0b3f0b9a1b0b4f9b1a1',
        teamName: 'World XI A',
        totalPlayers: 15,
        player: [
            {
                playerId: '60f3b0b3f0b9a1b0b4f9b1a2',
                playerName: 'Player A',
                score: 10,
            },
            {
                playerId: '60f3b0b3f0b9a1b0b4f9b1a3',
                playerName: 'Player B',
                score: 20,
            },
        ],
    },
    {
        _id: '60f3b0b3f0b9a1b0b4f9b1a4',
        teamName: 'Crackers',
        totalPlayers: 15,
        player: [
            {
                playerId: '60f3b0b3f0b9a1b0b4f9b1a5',
                playerName: 'Player C',
                score: 30,
            },
            {
                playerId: '60f3b0b3f0b9a1b0b4f9b1a6',
                playerName: 'Player D',
                score: 40,
            },
        ],
    },
];

收藏2 -(玩家)

const Players = [
    {
        _id: '60f3b0b3f0b9a1b0b4f9b1a2',
        playerName: 'Player A',
        rank: 2,
        totalRuns: 5000,
    },
    {
        _id: '60f3b0b3f0b9a1b0b4f9b1a3',
        playerName: 'Player B',
        rank: 1,
        totalRuns: 3050,
    },
    {
        _id: '60f3b0b3f0b9a1b0b4f9b1a5',
        playerName: 'Player C',
        rank: 3,
        totalRuns: 2050,
    },
    {
        _id: '60f3b0b3f0b9a1b0b4f9b1a6',
        playerName: 'Player D',
        rank: 4,
        totalRuns: 1000,
    },
];

结果:* 这是结果数组的样子 *

结果数组

const result = [
    {
        _id: '60f3b0b3f0b9a1b0b4f9b1a1',
        teamName: 'World XI A',
        totalPlayers: 15,
        player: [
            {
                playerInfo: {
                    _id: '60f3b0b3f0b9a1b0b4f9b1a2',
                    playerName: 'Player A',
                    rank: 2,
                    totalRuns: 5000,
                },
                playerName: 'Player A',
                score: 10,
            },
            {
                playerInfo: {
                    _id: '60f3b0b3f0b9a1b0b4f9b1a3',
                    playerName: 'Player B',
                    rank: 1,
                    totalRuns: 3050,
                },
                playerName: 'Player B',
                score: 20,
            },
        ],
    },
    {
        _id: '60f3b0b3f0b9a1b0b4f9b1a4',
        teamName: 'Crackers',
        totalPlayers: 15,
        player: [
            {
                playerInfo: {
                    _id: '60f3b0b3f0b9a1b0b4f9b1a5',
                    playerName: 'Player C',
                    rank: 3,
                    totalRuns: 2050,
                },
                playerName: 'Player C',
                score: 30,
            },
            {
                playerInfo: {
                    _id: '60f3b0b3f0b9a1b0b4f9b1a6',
                    playerName: 'Player D',
                    rank: 4,
                    totalRuns: 1000,
                },
                playerName: 'Player D',
                score: 40,
            },
        ],
    },
];
ohtdti5x

ohtdti5x1#

  1. $lookup-使用字段连接 TeamsPlayers 集合。并返回players数组字段。
  2. $set-设置player字段。
    2.1. $map-迭代player数组中的元素并返回一个新数组。
    2.1.1. $mergeObjects-将当前迭代的文档与结果 2.1.1.1 中带有playerInfo字段的文档合并。
    2.1.1.1. $first-从结果 2.1.1.1.1 中获取第一个匹配的文档。
    2.1.1.1.1. $filter-过滤players数组中与_id匹配的文档。
  3. $unset-删除字段:players字段和player.playerId字段。
db.Teams.aggregate([
  {
    "$lookup": {
      "from": "Players",
      "localField": "player.playerId",
      "foreignField": "_id",
      "as": "players"
    }
  },
  {
    $set: {
      player: {
        $map: {
          input: "$player",
          as: "p",
          in: {
            $mergeObjects: [
              "$$p",
              {
                playerInfo: {
                  $first: {
                    $filter: {
                      input: "$players",
                      cond: {
                        $eq: [
                          "$$p.playerId",
                          "$$this._id"
                        ]
                      }
                    }
                  }
                }
              }
            ]
          }
        }
      }
    }
  },
  {
    $unset: [
      "players",
      "player.playerId"
    ]
  }
])

Demo @ Mongo Playground

ymzxtsji

ymzxtsji2#

目前还不清楚您是希望在MongoDB查询中完成此操作,还是希望在javascript中聚合数据。如果是后者,那么它实际上只是Player数组中每个团队的Player数组上的嵌套Map,并通过id添加Players数组中的匹配元素。这里首先通过id创建一个Map的播放器,以实现高效访问。

const Teams = [{ _id: '60f3b0b3f0b9a1b0b4f9b1a1', teamName: 'World XI A', totalPlayers: 15, player: [{ playerId: '60f3b0b3f0b9a1b0b4f9b1a2', playerName: 'Player A', score: 10, }, { playerId: '60f3b0b3f0b9a1b0b4f9b1a3', playerName: 'Player B', score: 20, },], }, { _id: '60f3b0b3f0b9a1b0b4f9b1a4', teamName: 'Crackers', totalPlayers: 15, player: [{ playerId: '60f3b0b3f0b9a1b0b4f9b1a5', playerName: 'Player C', score: 30, }, { playerId: '60f3b0b3f0b9a1b0b4f9b1a6', playerName: 'Player D', score: 40, },], },];
const Players = [{ _id: '60f3b0b3f0b9a1b0b4f9b1a2', playerName: 'Player A', rank: 2, totalRuns: 5000, }, { _id: '60f3b0b3f0b9a1b0b4f9b1a3', playerName: 'Player B', rank: 1, totalRuns: 3050, }, { _id: '60f3b0b3f0b9a1b0b4f9b1a5', playerName: 'Player C', rank: 3, totalRuns: 2050, }, { _id: '60f3b0b3f0b9a1b0b4f9b1a6', playerName: 'Player D', rank: 4, totalRuns: 1000, },];

const playerInfoMap = new Map(Players.map((p) => [p._id, p]));

const result = Teams.map(({ player, ...team }) => ({
  ...team,
  player: player.map(({ playerId, ...player }) => ({
    ...player,
    ...(playerInfoMap.has(playerId)
      ? { playerInfo: playerInfoMap.get(playerId) }
      : { playerId }),
  })),
}));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

相关问题