如何用MongoDB聚合操作处理文档内嵌数组及用户资产统计?
assets Array in MongoDB Got it, let's break this down step by step. The goal is to isolate the assets array first, then run your filtering, skip, and limit operations on its elements. Here's how to do it properly:
Key Pipeline Stages Explained
First, let's assume your users collection has documents like this:
{ "_id": ObjectId("60d21b4667d0d8992e610c85"), "username": "jane_doe", "assets": [ {"category": "real_estate", "value": 450000}, {"category": "stocks", "value": 80000}, {"category": "crypto", "value": 12000}, {"category": "stocks", "value": 35000} ] }
1. Project Only the assets Array
Start by using $project to extract just the assets field (you can exclude _id to keep results clean):
{ $project: { assets: 1, _id: 0 } }
This stage outputs documents that only contain the assets array, nothing else.
2. Unwind the Array
Since operations like $match, $skip, and $limit work on individual documents (not array elements), you need to "unwind" the assets array. This converts each element in the array into its own separate document:
{ $unwind: "$assets" }
After this stage, you’ll have a separate document for every asset entry from all users.
3. Filter the Assets
Use $match to filter the unwound asset documents based on your criteria. For example, if you only want stock assets worth more than 50k:
{ $match: { "assets.category": "stocks", "assets.value": { $gt: 50000 } } }
4. Apply Skip and Limit
Now you can use $skip to skip a certain number of matching assets, and $limit to restrict the number of results:
{ $skip: 0 }, // Adjust the number to skip as needed { $limit: 2 } // Keep only 2 results
5. Optional: Re-group into an Array
If you want the final result to be a single array of filtered assets (instead of individual documents), use $group to collect them back together:
{ $group: { _id: null, filtered_assets: { $push: "$assets" } } }
Full Aggregation Pipeline Example
Putting it all together, here's a complete pipeline that projects, filters, skips, limits, and re-groups:
db.users.aggregate([ // Project only assets { $project: { assets: 1, _id: 0 } }, // Unwind to process individual assets { $unwind: "$assets" }, // Filter for stocks over 50k { $match: { "assets.category": "stocks", "assets.value": { $gt: 50000 } } }, // Skip first 0 results (adjust as needed) { $skip: 0 }, // Keep only 2 assets { $limit: 2 }, // Re-group into a single array { $group: { _id: null, filtered_assets: { $push: "$assets" } } } ])
Quick Notes
- If you want to run these operations per user (instead of across all users), add a
$matchstage at the beginning to target specific users first. For example:{ $match: { username: "jane_doe" } } - If you don’t need to re-group, you can omit the final
$groupstage—you’ll get individual asset documents as output.
内容的提问来源于stack exchange,提问作者Yoosif Sherif

