如何将集合子数组对象与其他集合中存在的实际对象聚合?
例如:这就是我的收藏品的样子
集合 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,
},
],
},
];
$lookup
- 使用字段加入 Teams 和 Players 集合。并返回 players
数组字段。
$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
匹配的文档。
$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"
]
}
])
目前尚不清楚您是否希望在
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; }