Reputation: 977
I am trying to update sub documents with mongoose using the request.body
without passing of the sub documents _id
. Updating works but mongoose is removing the _id
from the sub documents.
Assume the following schemas
// schemas.js
const mongoose = require('mongoose');
const motorSchema = new mongoose.Schema({
type: String,
volume: Number,
});
const carSchema = new mongoose.Schema({
manufacturer: String,
model: String,
motors: [motorSchema],
});
const userSchema = new mongoose.Schema({
username: String,
email: String,
cars: [carSchema]
});
const mongoose = require('mongoose');
// import schemas
const userSchema = require('userSchema');
const carSchema = require('carSchema');
const motorSchema = require('motorSchema');
// create models
const User = mongoose.model("User", userSchema);
const Car = mongoose.model("Car", carSchema);
const Motor = mongoose.model("Motor", motorSchema);
module.exports.updateCar = async function (request, response) {
const condition = {
_id: new mongoose.Types.ObjectId(request.body.userId),
"cars._id": new mongoose.Types.ObjectIt(request.body.carId)
};
// Build object for partial update
const set = {};
for(let field in reqest.body){
set[`cars.$.${field}`] = request.body[field];
}
const update = {
$set = set;
}
User.findOneAndUpdate(condition, update, {new: true, overwrite: false},
(error, user) => {
if(error) {response.send(error)}
response.json(user);
}
}
The problem is that all my _id
properties will be overwritten in the motors array. How can I force mongoose as default to not change the _id
properties?
Upvotes: 0
Views: 39
Reputation: 16033
If I understand you correctly, the equivalent mongoDB syntax will use arrayFilters
, so you can modify your query to use that as well:
For example:
User.findOneAndUpdate(
condition,
{$set: {"cars.$[item].size": "large"}},
{arrayFilters: [{"item._id": new mongoose.Types.ObjectIt(request.body.carId)}]}
)
See how it works on the playground example
According to this method, your code needs the arrayFilters
in the options part and the $[<identifier>]
in the $set
part of the query:
const set = {};
for(let field in reqest.body){
set[`cars.$[item].${field}`] = request.body[field];
}
const update = {
$set = set;
}
User.findOneAndUpdate(
condition,
update,
{
arrayFilters: [{"item._id": new mongoose.Types.ObjectIt(request.body.carId)}],
new: true, overwrite: false
},
(error, user) => {
if(error) {response.send(error)}
response.json(user);
}
Upvotes: 1