I'm working in the MEAN stack, and I'm stuck on a Mongoose issue. Updates are working fine for individual documents(single key:value), but when I attempt to update a nested object with a new object, it's just deleting the original object and not inserting the new one.
Using an identical query directly in mongo, within the terminal, works perfectly. But from my Mongoose model, I get the above behavior.
My final desired query is more complicated and uses many variables, so I've simplified the code to the following to highlight the issue:
Setup.update({name: "main"}, {$set: {"schedule.sunday.eleven_pm": { associates: 111, supervisors: 111}}}, function(err){
if(err){
console.log(err);
}
else{
console.log('successfully updated main schedule setup')
Setup.find({}, function(err, setup){
if(err){
console.log(err);
}
else{
res.json(setup);
}
})
}
});
Gives me this in my db:
"eleven_pm" : {
}
But from terminal, the same query (cut and pasted from my mongoose query, just added 'db.setups' to beginning:
db.setups.update({name: "main"}, {$set: {"schedule.sunday.eleven_pm": { associates: 111, supervisors: 111}}})
Gives me this, the desired result:
"eleven_pm" : {
"associates" : 111,
"supervisors" : 111
}
I've tried writing this as a findOneAndUpdate(), but encountered the same behavior. Am I doing something unorthodox here?
Any help greatly appreciated.
A small change in my database structure was not amended in my Mongoose "Schema", and the difference between the two led to the unusual query behavior explained above.
Related
I scouted around to find the right solution for inserting a large amount of documents to MongoDB using Mongoose.
My current solution looks like this:
MongoClient.saveData = function(RecordModel, data, priority, SCHID, callback){
var dataParsed = parseDataToFitSchema(data, priority, SCHID);
console.log("Model created. Inserting in batches.");
RecordModel.insertMany(dataParsed)
.then(function(mongooseDocuments) {
console.log("Insertion was successful.");
})
.catch(function(err) {
callback("Error while inserting data to DB: "+err);
return;
})
.done(function() {
callback(null);
return;
});
}
But it appears to me there are other offered solutions out there. Like this one:
http://www.unknownerror.org/opensource/Automattic/mongoose/q/stackoverflow/16726330/mongoose-mongodb-batch-insert
Using collection.insert. How is that different to the Model.insertMany?
Same goes for update, my previous question: What is the right approach to update many records in MongoDB using Mongoose
Asks how do I update big chunk of data with Mongoose, defined by _id. The answer suggests to use collection.bulkWrite while I am under impression Model.insertMany can do it too.
I'm working with the mean stack I'm trying to update the following object:
{
_id : "the id",
fields to be updated....
}
This is the function that does the updating:
function updateById(_id, update, opts){
var deferred = Q.defer();
var validId = new RegExp("^[0-9a-fA-F]{24}$");
if(!validId.test(_id)){
deferred.reject({error: 'invalid id'});
} else {
collection.findOneAndUpdate({"_id": new ObjectID(_id)}, update, opts)
.then(function(result){
deferred.resolve(result);
},
function(err){
deferred.reject(err);
});
}
return deferred.promise;
}
This works with some of my objects, but doesn't work with others.
This is what is returned when it fails to update:
{
ok: 1,
value:null
}
When the function is successful in updating the object it returns this:
{
lastErrorObject: {}
ok: 1
value: {}
}
It seems like Mongo is unable to find the objects I'm trying to update when it fails. However, I can locate those objects within the Mongo shell using their _id.
Does anybody know why the driver would be behaving this way? Could my data have become corrupt?
Cheers!
I found the answer and now this question seems more ambiguous so I apologize if it was confusing.
The reason I was able to find some of the documents using ObjectID(_id) was because I had manually generated some _id fields using strings.
Now I feel like an idiot but, instead of deleting this question I decided to post the answer just in case someone is running into a similar issue. If you save an _id as a string querying the collection with the _id field changes.
querying collection with MongoDB generated _ids:
collection.findOneAndUpdate({"_id": new ObjectID(_id)}, update, opts)
querying collection with manually generated _ids:
collection.findOneAndUpdate({"_id": _id}, update, opts)
In the second example _id is a string.
Hope this helps someone!
How can I create the not contains query that returns true if the item does not contain a certain value. I'm running mongoDB if it is relevant.
I can use the contains successfully however receive an error when I introduce the not. I've tried it with find and where but get the same regex error both times. I can add the exact error if its relevant.
Working version:
model.find({attribute: {'contains': value}})
.exec(function(err, users) {
// happy code
});
The following complains about some regex error:
model.find({attribute: {not: {'contains': value}}})
.exec(function(err, users) {
// sad code
});
There was an issue raised and closed in 2013 about this. Maybe something changed recently?
https://github.com/balderdashy/waterline/issues/22
Alexei, I don't think this is supported by waterline currently. There is a related issue which is marked as feature and that you can track:
https://github.com/balderdashy/waterline/issues/666
So far, you can only use native feature of Mongodb I think.
Model.native(function(err, collection) {
collection.find({
"attribute" : {
$ne : value, //Not Equal
//OR
$nin : [value1, value2]// Not In
}
}).toArray(function(err, docs) {
if (err) return callback(err, docs);
res.json(null, docs);
});
});
I have this:
exports.deleteSlide = function(data,callback){
customers.findOne(data.query,{'files.$':1},function(err,data2){
if(data2){
console.log(data2.files[0]);
data2.files[0].slides.splice((data.slide-1),1);
data2.files[0].markModified('slides');
data2.save(function(err,product,numberAffected){
if(numberAffected==1){
console.log("manifest saved");
var back={success:true};
console.log(product.files[0]);
callback(back);
return;
}
});
}
});
}
I get the "manifest saved" message and a callback with success being true.
When I do the console.log when I first find the data, and compare it with the console.log after I save the data, it looks like what I expect. I don't get any errors.
However, when I look at the database after running this code, it looks like nothing was ever changed. The element that I should have deleted, still appears?
What's wrong here?
EDIT:
For my query, I do {'name':'some string','files.name':'some string'}, and if the object is found, I get an array of files with one object in it.
I guess this is a subdoc.
I've looked around and it says the rules for saving subdocs are different than saving the entire collection, or rather, the subdocs are only applied when the root object is saved.
I've been going around this by grabbing the entire root object, then I do loops to find the actual subdoc I that I want, and after I manipulate that, I save the whole object.
Can I avoid doing this?
I'd probably just switch to using native drivers for this query as it is much simpler. (For that matter, I recently dropped mongoose on my primary project and am happy with the speed improvements.)
You can find documentation on getting access to the native collection elsewhere.
Following advice here:
https://stackoverflow.com/a/4588909/68567
customersNative.update(data.query, {$unset : {"slides.1" : 1 }}, function(err){
if(err) { return callback(err); }
customersNative.findAndModify(data.query, [],
{$pull: {'slides' : null } }, {safe: true, 'new' : true}, function(err, updated) {
//'updated' has new object
} );
});
I'm working with mongodb, node.js and socket.io and I'm trying to reduce the number off access to the database. I need to update a line ; and after to return the updated line this is how I do :
db.collection('users').update({_id:targetID}, {$set: { 'property': 'value' }}, {safe:true}, function(err, result) {
db.collection('users').find({_id:targetID}).toArray(function(error, results){
//a socket.io resend the content
});
});
It works, but I really fell like I'm having a useless step here. The callback of the update function seems to be a boolean.
BTW, is there a better documentation than this one : http://docs.mongodb.org/manual/applications/update/ ? I'd like to find a list of properties and methods. The {safe:true} for instance. It seems not working without it but I can't find it in the reference.
Maybe I'm completely wrong and this is not the way I should do it. If you have a better idea... :)
You can use findAndModify to do this efficiently:
db.collection('users').findAndModify(
{_id: targetID}, [],
{$set: { 'property': 'value' }},
{new: true}, // Return the updated doc rather than the original
function(err, result) {
// result contains the updated document
}
);