MongoDB查询后使用Object.assign()需调用_doc问题求助
Hey there! Let's break down why your original code needed b._doc and look at better, more maintainable ways to handle this.
Why Object.assign({}, b) didn't work
Mongoose returns Document objects from queries, not plain JavaScript objects. These documents have built-in getters, setters, and Mongoose-specific methods—so when you try to copy them directly with Object.assign, you're copying the Document instance itself, not just the raw data. Accessing _doc works because it's Mongoose's internal property that stores the raw document data, but it's not an official API and can break if Mongoose changes its internal structure.
Option 1: Use lean() for Plain JS Objects (Recommended)
The simplest fix is to add .lean() to your query. This tells Mongoose to return plain JavaScript objects instead of Document instances, so you can manipulate them directly without dealing with Mongoose's wrapper:
Book.find(query) .lean() // Returns plain JS objects instead of Mongoose Documents .exec() .then(books => _.map(books, b => ({ ...b, name: b.name[version] }))) .then(books => reply(books)) .catch(err => reply(err))
We're using the spread operator (...b) here instead of Object.assign for cleaner syntax, but either works with plain objects.
Option 2: Convert Documents to Objects with toObject()
If you need to keep using Mongoose Document instances (e.g., to call instance methods later), use the official .toObject() method to convert them to plain objects safely:
Book.find(query) .exec() .then(books => _.map(books, b => { const bookData = b.toObject(); // Official way to get raw data return { ...bookData, name: bookData.name[version] }; })) .then(books => reply(books)) .catch(err => reply(err))
This is better than accessing _doc directly because toObject() is a supported API that won't unexpectedly change.
Option 3: Handle Transformation at the Database Level (Most Efficient)
For even better performance, let MongoDB do the work of transforming the field using an aggregation pipeline. This way you don't have to process the data in your application code:
Book.aggregate([ { $match: query }, // Filter books like find() { $project: { title: 1, name: `$name.${version}` // Directly pick the desired version } } ]) .exec() .then(books => reply(books)) .catch(err => reply(err))
This approach reduces the amount of data transferred from the database and cuts down on application-side processing.
Final Notes
- Avoid using
_docwhenever possible—it's an internal implementation detail, not a public API. lean()is your go-to for read-only operations where you don't need Mongoose's Document features.- Aggregation is ideal if you want to offload processing to the database.
内容的提问来源于stack exchange,提问作者acmoune

