MongoDB多文档数据获取问题:使用Aggregate需返回多条记录
Hey Dave, let's tackle this problem you're having with MongoDB's aggregate pipeline. It sounds like you're using aggregate() but ending up with a single aggregated result instead of the multiple individual records you need—let's fix that.
First, let's recap your Book Schema to make sure we're on the same page:
var BookSchema = new Schema({ BookName: { type: String, required: true, index: { unique: true }}, userAssignedId: { type: Schema.Types.ObjectId}, BookAuthorId: { type: Schema.Types.ObjectId, required: true}, BookVersionId :{ type: Schema.Types.ObjectId, required: true} });
Key Issue to Fix: Avoid Unnecessary $group Stages
If your current aggregate pipeline uses $group with _id: null, that's why you're getting a single merged result—this syntax aggregates all documents into one. To keep multiple records, either:
- Remove the
$groupstage entirely (to retain individual book documents, possibly with joined data), or - Use
$groupwith a specific field (likeBookAuthorId) to group related records while keeping groups separate.
Example 1: Return Individual Book Records with Joined Data
If you want to fetch each book as a separate record, plus join related data (like author, version, assigned user), use $lookup to join collections and $unwind to flatten the joined arrays (without merging records):
Book.aggregate([ // Join with authors collection (replace "authors" with your actual collection name) { $lookup: { from: "authors", localField: "BookAuthorId", foreignField: "_id", as: "bookAuthor" } }, // Join with versions collection { $lookup: { from: "versions", localField: "BookVersionId", foreignField: "_id", as: "bookVersion" } }, // Join with users collection (for assigned user, optional) { $lookup: { from: "users", localField: "userAssignedId", foreignField: "_id", as: "assignedUser" } }, // Flatten joined arrays to single objects (keep null/empty records if no match) { $unwind: { path: "$bookAuthor", preserveNullAndEmptyArrays: true } }, { $unwind: { path: "$bookVersion", preserveNullAndEmptyArrays: true } }, { $unwind: { path: "$assignedUser", preserveNullAndEmptyArrays: true } }, // Optional: Shape the output to only include fields you need { $project: { _id: 1, BookName: 1, Author: "$bookAuthor.AuthorName", // Adjust to your Author schema's field Version: "$bookVersion.VersionNumber", // Adjust to your Version schema's field AssignedUser: "$assignedUser.Username" // Adjust to your User schema's field } } ]) .exec((err, results) => { if (err) console.error(err); console.log(results); // This will return an array of individual book records! });
Example 2: Group Records but Keep Multiple Entries per Group
If you want to group books (e.g., by author) but still see all books in each group, use $group with $push to collect related records into an array:
Book.aggregate([ { $lookup: { /* Same author join as above */ } }, { $unwind: "$bookAuthor" }, // Group books by author, keeping all books in each group { $group: { _id: "$BookAuthorId", AuthorName: { $first: "$bookAuthor.AuthorName" }, BooksByAuthor: { $push: { BookName: "$BookName", Version: "$bookVersion.VersionNumber" } } } } ])
This will return one record per author, each containing an array of their books.
Quick Tip for Historical Data
You mentioned a historical data schema—if you need to join that too, just add another $lookup stage pointing to your historical collection (e.g., bookHistories) and link it via the book's _id:
{ $lookup: { from: "bookHistories", localField: "_id", foreignField: "BookId", // Assuming your history records have a BookId field as: "History" } }
内容的提问来源于stack exchange,提问作者Dave1

