MongoDB聚合查询:如何调整‘今日已评测游戏’结果格式?
Absolutely, you can handle this transformation directly within MongoDB's aggregation pipeline—no need to post-process with JavaScript! Let's fix that array-wrapping issue with a couple of straightforward steps.
The core problem here is that the $lookup stage always returns an array for the game field, even when there’s only one matching document in the Game collection. That’s why you’re seeing the nested [{}] structure in your results. Here are two ways to fix this right in your pipeline:
Option 1: Unwrap the array with $unwind
If you just want to convert the game array into a direct object (keeping the nested game key), add a $unwind stage immediately after $lookup:
db.Review.aggregate([ { $match: { publishedDate: { $gte: cutoff } } }, { $sortByCount: '$game.id' }, { $limit: 10 }, { $lookup: { from: 'Game', localField: '_id', foreignField: 'id', as: 'game' } }, { $unwind: '$game' }, // Converts the single-element array to a plain object { $project: { 'game.id': 1, 'game.name': 1, 'game.topCriticScore': 1, 'game.firstReleaseDate': 1, 'game.tier': 1, '_id': 0 } } ]);
This will change your output to:
[ { "game": { /* game document */ } }, { "game": { /* game document */ } }, ... ]
Option 2: Flatten the structure entirely
If you’d prefer to have the game’s fields as top-level properties (and keep the review count from $sortByCount), use $arrayElemAt with $replaceRoot to merge the game data and review count into a single flat document:
db.Review.aggregate([ { $match: { publishedDate: { $gte: cutoff } } }, { $sortByCount: '$game.id' }, { $limit: 10 }, { $lookup: { from: 'Game', localField: '_id', foreignField: 'id', as: 'game' } }, { $addFields: { game: { $arrayElemAt: ['$game', 0] }, // Extract the single game from the array reviewCount: '$count' // Rename the count to a more descriptive field } }, { $replaceRoot: { newRoot: { $mergeObjects: ['$game', { reviewCount: '$reviewCount' }] } // Merge game data and count } }, { $project: { id: 1, name: 1, topCriticScore: 1, firstReleaseDate: 1, tier: 1, reviewCount: 1 } } ]);
This will give you clean, flat results like:
[ { "id": "game_123", "name": "Epic Adventure Game", "topCriticScore": 89, "firstReleaseDate": ISODate("2024-01-15T00:00:00Z"), "tier": "A", "reviewCount": 7 }, // More results... ]
Pick the approach that best fits your desired output structure—both work entirely within MongoDB’s aggregation framework, so you can skip the client-side mapping step.
内容的提问来源于stack exchange,提问作者MattEnth

