My schema is as follows : -
var Schema1 = new mongoose.Schema({
name: String,
description: String,
version: [{
id: String,
status: Number
}]
});
I want to unset the version field. I try the following code :-
Schema1.update({}, {
$unset: {
version: 1
}
}, {
multi: true
}).exec(function(err, count) {
console.log(err, count)
});
It gives me the following output :-
null 10
But the output contain the version field :-
{
name : 'a',
description : 'sdmhf',
version : []
}
The above code remove the data but I want to remove the version field from my collection as well. Can you tell me how to do that?
There's nothing wrong with your code. Mongoose is actually deleting those fields in the documents (which I assume is what you expected). You can see by opening a mongo shell into your database and searching all your documents before and after the update (use db.yourcollection.find({}))
Why does an empty array still appear even when it's removed from every document in the collection? Mongoose will ensure the documents returned will obey the schema that you define. So even if Mongoose finds no version property pointing to an Array in the actual document, it will still present an empty array when the matching documents are returned.
You can verify this yourself by adding some arbitrary property (pointing to an Array) to your schema and running a .find({}) again. You'll see that Mongoose will return these properties in every document even though you never saved them to the database. Similarly, if you add non-Array properties like Strings, Booleans, etc, Mongoose will return those as long as you specify a default value.
If you want to drop version for good (as you mentioned in your comment) you can drop it from your Mongoose schema after you've completed the $unset.
This worked for me
doc.field = undefined
await doc.save()
Related
Background:
I have an array (A) of new objects that need to be added to an array field in Mongoose. if successful it should print to screen the newly updated object but it prints null. I checked the database and confirmed it also does not update at all. I followed the docs to use the $push and $each modifiers here:
https://www.mongodb.com/docs/manual/reference/operator/update/each/
Desired Behaviour:
I would like each object in (A) to be added to the Array field, not (A) itself. Upon success, it should print to screen the newly updated object.
Attempted Approach:
let identifier={customer:{external_id:'12345'}}
let array = [{value:30},{value:30}]
User.findOneAndUpdate(identifier,{$push:{points:{$each:array}}},{new:true})
.then((result)=>{
console.log(result)
})
Attempted Resolutions:
I tested if the issue was with the identifier parameter, but it works fine when the update parameter does not have $each (i.e. it pushes the whole array (A) into the array field)
I thought about using $addToSet like in the solution below, but as you can see in the sample code above, I want to push all objects even if they are not unique:
Mongoose - Push objects into nested array
use dot "." notation for embedded field
let filter={'customer.external_id':'12345'}
let array = [{value:30},{value:30}];
let update = { $push: { points: { $each: array } } };
User.findOneAndUpdate(filter,update,{new: true})
.then((result)=>{
console.log(result)
})
It turns out the IDs did not match. There was no issue with the code. Sorry guys.
I've a schema for a store inventory. The location has locationcategories array in the schema and inside that array, I have items[] array.
My issue is updating this items[] inside the locationcategories[]. I use the mongodb shell to update that array (using updateOne()) and it works (update my items[] inside locationcategories[]) but when I do it using mongoose model ("Locations") it doesn't update, in my console, it just shows { n: 1, nModified: 0, ok: 1 } which indicate that everything was found but didn't modify anything. When I check the db, it doesn't have any new items added.
Here is code I use in mongoshell which updates items[] inside locationcategories[]
db.locations.updateOne({"locationname" :"My Town", "locationcategories":{"$elemMatch":{"categoryname": "Media"}}},{$push:{"locationcategories.$.items": {"test":"test"}}})
In my application server route (expressjs) I enter the following:
Location.updateOne(
{ "locationname": "My Town", "locationcategories": {"$elemMatch":{"categoryname": "Media"}}},
{$push: {"locationcategories.$.items": {"test":"test"}}},
{new : true, upsert: true },
function (error, results) {
console.log("findByIdAndUpdate results :", results);
}
);
my mongooose schema-model:
var Schema = mongoose.Schema;
var locationSchema = new Schema({
locationname: String,
locationdescription: String,
locationcategories: [{ categoryorder: Number, categoryname: String,
categorydescription: String, items[{itemname: String }]}],
items: [{categoryid : String, itemorder: Number, itemname: String, itemdescription: String, itemprice: Number }],
created_at: Date
});
var Location = mongoose.model('Location', locationSchema);
export default Location;
I'm using mognodb version 4.02
Model.updateOne should work but it is not adding anything to my db. I read many of the stackoverflow.com issues but I couldn't find anything that indicate an issue except this old question from years ago which he had an issue updating array inside array. I find it hard to believe that there is an issue and no one addressed it after all those years but I might be wrong.
If the mongo shell execute and add to db correctly, it leads me to believe that the mongoose model or schema are responsible for the issue or my updateOne() code is wrong.
Any idea why?
Got it. So I changed items inside the locationcategories[] to categoryItems[] and it works.
The .$ operator looks for the first array with the name items which was items outside but I was posting the data to the model's first array.
Make sure you name the arrays in your model with unique names and point the $push to the correct array.
Also upgrded mongodb from version 4.0 to the latest one 4.41.
I'm using a Mongoose/MongoDB and I'm getting some odd behaviour when I try to use the spread syntax to return values from a document after I call .save() on it.
// Npc is a Mongoose schema
const npc = new Npc({
...input,
creator: userId
});
const createdNpc = await npc.save();
I have tried using the spead operator, but the name and description keys do not exist.
return {
...createdNpc
creator: userFromId(npc.creator)
}
however when I access those values directly they ARE defined
return {
description: createdNpc.description,
name: createdNpc.name,
creator: userFromId(npc.creator)
};
I've made sure that the spelling of description and name are correct. I've tried logging both {...createdNpc} and {...createdNpc, description: createdNpc.description, name: createdNpc.name}. In the logs I've confirmed that name and description are both not defined (the keys don't exist) inside of {...createdNpc}
I have also tried logging createdNpc and {...createdNpc} and have confirmed that they return different values.
here's createdNpc:
{
_id: 5d8d5c7a04fc40483be74b3b,
name: 'NPC Name',
description: 'My Postman NPC',
creator: 5d8d50e0b5c8a6317541d067,
__v: 0
}
it doesn't actually look like a Mongoose Document at all. I would post the result of {...createdNPC} to show the difference but it's a huge code snippet and I don't want to clutter the question. I'm happy to provide it if it will help!
I'm still very new to MongoDB & Mongoose. Why would using the spread syntax on a Mongoose Document change its value?
I don't think this should be relevant to the question but just in case I'll also mention this is for a graphql resolver.
This is because Mongoose uses getters for all of its attributes. Before you use the spread operator, call createdNpc.toObject() to get a normal Object.
I am attempting to perform a relatively simple update using Mongoose:
var location = locationService.getLocation(typedLat, typedLong, travelRadius);
DocumentModel.update({_id : passedInId }, { location : location }, function(err, resp){
next(err, resp);
});
In this case passedInId is the string:
"561ee6bbe4b0f25b4aead5c8"
And in the object (test data I created) the id is:
"_id": ObjectId("561ee6bbe4b0f25b4aead5c8")
When I run the above however, matched documents is 0. I assume this is because passedInId is being treated like a string, however when I type it to an ObjectId:
var queryId = ObjectId(passedInId)
The result is the same, the document doesn't match. What am I missing? This seems like it should be obvious....
Mongoose will correctly interpret a string as an ObjectId. One of the following must be the case:
That record is not in the collection. Run a query in the mongo shell to check.
Mongoose I'd looking in collection other than the one containing your test data. Remember, by default, mongo will lowercase the name under which you register your model and will add an a "s" to it.
Lastly, and your answer speaks to this, maybe your model it's just not being updated with any new information.
This behavior was because I had not yet updated the model in mongoose to include the location element. There is no error, it just doesn't match or do anything.
I have a schema defined in mongoose as follow:
var VolunteerSchema = new Schema ({
......
other fields
.....
preferLocations:[{
type: Schema.ObjectId,
ref: 'Location'
}]
.....
});
I am using volunteer.save() method to update the model.
While updating to volunteer model i get the error as follow:
{ [DivergentArrayError: For your own good, using `document.save()` to update an
array which was selected using an $elemMatch projection OR populated using skip,
limit, query conditions, or exclusion of the _id field when the operation resul
ts in a $pop or $set of the entire array is not supported. The following path(s)
would have been modified unsafely:
preferLocations
Use Model.update() to update these arrays instead.]
message: 'For your own good, using `document.save()` to update an array which
was selected using an $elemMatch projection OR populated using skip, limit, quer
y conditions, or exclusion of the _id field when the operation results in a $pop
or $set of the entire array is not supported. The following path(s) would have
been modified unsafely:\n preferLocations\nUse Model.update() to update these a
rrays instead.',
name: 'DivergentArrayError' }
While updating the location I collect the _ids field in array and asigned to preferLocations as given below:
volunteer.preferLocations = locationIdsArray;
I don't get the error when I remove this line.What am I doing wrong?
When using $elemMatch in a projection, do not use document.save(). Instead, manually update your document using Model.update(). In your case you should try
volunteer.findOneAndUpdate(
{
_id: ObjectId("567452bae5b25d6e6c1a0f7e"),
localization: { '$elemMatch': { language: 'de' } }
},
{
$set: { 'localization.$.name' : "Neuer Name" }
}).exec(//...
});
click here more details