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

问题描述 投票:0回答:2

如何将集合子数组对象与其他集合中存在的实际对象聚合?

例如:这就是我的收藏品的样子

集合 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,
            },
        ],
    },
];
javascript node.js mongodb mongodb-query aggregation-framework
2个回答
3
投票
  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"
    ]
  }
])

演示@Mongo Playground


1
投票

目前尚不清楚您是否希望在

MongoDB
查询中完成此操作,或者是否想在 JavaScript 中聚合数据。如果是后者,那么它实际上只是
Player
数组中每个团队内的
Teams
数组上的嵌套映射,并通过 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; }

© www.soinside.com 2019 - 2024. All rights reserved.