I am having trouble trying to insert a new user in my database when using findOneAndUpdate
with upsert and setDefaultsOnInsert
set to true. What I am trying to do is to set the default values of the following schema:
var userSchema = new mongoose.Schema({
activated: {type: Boolean, required: true, default: false},
facebookId: {type: Number, required: true},
creationDate: {type: Date, required: true, default: Date.now},
location: {
type: {type: String},
coordinates: []
},
email: {type: String, required: true}
});
userSchema.index({location: '2dsphere'});
findOneAndUpdate
code:
model.user.user.findOneAndUpdate(
{facebookId: request.params.facebookId},
{
$setOnInsert: {
facebookId: request.params.facebookId,
email: request.payload.email,
location: {
type: 'Point',
coordinates: request.payload.location.coordinates
}
}
},
{upsert: true, new: true, setDefaultsOnInsert: true}, function (err, user) {
if (err) {
console.log(err);
return reply(boom.badRequest(authError));
}
return reply(user);
});
As you can see I also store the latitude and longitude of the user and that's where the problem begins. When findOneAndUpdate
gets called I get this error:
{ [MongoError: exception: Cannot update 'location' and 'location.coordinates' at the same time]
name: 'MongoError',
message: 'exception: Cannot update \'location\' and \'location.coordinates\' at the same time',
errmsg: 'exception: Cannot update \'location\' and \'location.coordinates\' at the same time',
code: 16836,
ok: 0 }
When I remove the 2dsphere index and all location related code It does set my creationDate. I am doing something wrong?
The setDefaultsOnInsert
option uses the $setOnInsert
operator to perform its function, and it looks like that's conflicting with your own use of $setOnInsert
to set the location
.
A workaround would be to remove the setDefaultsOnInsert
option and put it all in your own $setOnInsert
operator:
model.user.user.findOneAndUpdate(
{facebookId: request.params.facebookId},
{
$setOnInsert: {
activated: false,
creationDate: Date.now(),
email: request.payload.email,
location: {
type: 'Point',
coordinates: request.payload.location.coordinates
}
}
},
{upsert: true, new: true},
function (err, user) {
if (err) {
console.log(err);
return reply(boom.badRequest(authError));
}
return reply(user);
});