Why i can't replace field in mongoose document? - mongodb

vk_account.settings is an Array in mongoose schema.
vk_account.save(function(err, vk_account) {
if(err) return cb(err, null);
vk_account.Sources = updated_sources;
vk_account.settings = account_setting;
cb(null, vk_account);
})
I want to replace vk_account.settings(Array) to one certain object from the vk_account.settings, which is account_setting(Object), but when I replace it, it does not get replaced and vk_account.settings as before has old value.
As I understand it, the mongoose prohibits and does not assign an Object to a variable of type Array, but I don't want to save it, I just want to send it to the client and forget.

Firstly you cannot assign same value for save as well as for response vk_account... Then you have to change the instance to object using toObject() and then you can add keys in it
vk_account.save(function(err, vk) {
if(err) return cb(err, null);
var object = vk.toObject();
vk.Sources = updated_sources;
vk.settings = account_setting;
cb(null, vk);
})

Related

How to send ISODate in meteor.call method

I am creating an array of objects in client side in the meteor, and each object have modified date inside it as mentioned below:
Client Side:
student;
here student is an array of an object contains name, id, roll_no
var array = [];
student.forEach(function(singleStud, index){
var single_obj ={
"name":singleStud.name,
"student_id":singleStud.id,
"roll_no":singleStud.roll_no,
"college_name":"ABC college",
"college_id":"xyz Id",
"created_date": new Date()
}
array.push(single_obj);
},this)
Meteor.call('saveDetails', array, function (error, result) {
console.log("data Saved Successfully");
});
Server Side:
I have used plugin mikowals:batch-insert to insert an array which is equivalent to insertMany in mongo.
Meteor.methods({
"saveDetails": function (array) {
try {
studentDetails.batchInsert(array);
return true;
} catch (err) {
return err;
}
}
});
when I save it the created_date is saving it as a string ("2018-04-23T10:26:26.766Z"), but I want it to be saved it as a date data type (ISODate("2018-04-23T10:26:26.766Z")).
How can I achieve from the client side in meteor.call ???
This is actually a bug in mikowals:batch-insert. mikowals-batch-insert recursively attempts to convert objects into a JSON format friendly with MongoDB. As part of this process, it uses underscore clone to make shallow copies of primitive types. While Date is a primitive, it cannot be cloned with _.clone, so it mutates your date to a string (eww). You should open an issue with mikowals:batch-insert.
Regardless, you shouldn't be defining this data on the client. The client could maliciously inject false information (which could break your application's logic). Instead, you should map over the input and inject the date into incoming objects.

Overwrite object in mongodb

This should be simple but it is surprisingly difficult and extremely frustrating. I am trying to overwrite an 'Object' field in mongodb with a new Object that the user creates in my client webpage. I have validated that all other fields I am passing to the update operation are in fact being updated, with the exception of the javascript object. Instead of it updating with the object I am passing (While I validated is being populated with the object I am passing through), it just updates it back to {} instead of whats being passed:
{ nodes:[ { w: 120, h: 80,type: 'InHive',left: 184,top: 90,text: 'item',query: 'hey',name: 'sample',id: '7686132d-6fcf-4a3b-baa2-b1c628e0b2d6' } ], edges: [], ports: [],groups: [] }
When I attempt to update the data field outside of the meteor method, directly from the mongo console interface, it overwrites that field successfully with the javascript object. What am I doing wrong here, because I cant for the life of me figure this one out?
Server Method
'updateOneWorkflow': function(id, field, object) {
this.unblock;
if (Meteor.userId()) {
var _username = Meteor.user().username;
MYCOLLECTION.update({
_id: id
}, {
$set: {
[field]: object, //this just gets reset back to {} whenever this update method is called
"metadata.last_modified_dt": new Date(), //this gets updated
"metadata.modified_by": Meteor.userId(), //this gets updated
'metadata.modified_by_username': _username //This gets updated
}
});
} else {
throw new Meteor.Error(403, "You are not authorized to perform this function");
}
}
Client Call:
var _jsonformat = toolkit.exportData();
var currentid = Session.get('rulesRowClicked')._id;
console.log(_jsonformat);
Meteor.call('updateOneWorkflow' , currentid, 'data', _jsonformat, function(err, res){
if(err){
toastr.error('Failed to save result ' + err);
}
else{
toastr.success('Saved workflow');
}
});
I believe your problem is stemming from this line: [field]: object. I don't believe that's a proper method of dynamically accessing an object's field. Instead, try to dynamically update the field as so:
'updateOneWorkflow': function(id, field, object) {
this.unblock;
if (Meteor.userId()) {
var _username = Meteor.user().username;
var newObj = {
"metadata": {
"last_modified_dt": new Date(),
"modified_by": Meteor.userId(),
"modified_by_username": _username
}
};
newObj[field] = object;
MYCOLLECTION.update({
_id: id
}, {
$set: newObj
});
} else {
throw new Meteor.Error(403, "You are not authorized to perform this function");
}
}
The issue was crazier than I expected. If you are using Meteorjs and you are using the Aldeed Schema 2 collection framework, it seems to completely ignore updates/inserts of json objects even if you set the field type to Object, unless you set up the exact same schema as the object (including nested array objects) and attach it to your collection. Dumbest thing Ive ever seen, no idea why nothing warns you of this. I removed the schema attachment and it worked.

How to find a document from mongodb using mongoose based on query and then insert some data to it and save back?

I have my Model as
var Model = {"name":String,"email":String,"notes":[{"time":Date,"title":String,"description":String}]
And I want to find document based on the email, and then add a note to the array. And then save it back.
What I tried is,
var updatedNote = {};
Model.findOne({'email':'test#test.com'},function(err, note){
for(var property in note._doc){
if(note._doc.hasOwnProperty(property)){
updatedNote[property] = note._doc[property];
};
}
updatedNote.notes.push(newNote);
note._doc = updatedNote;
note.save(function(err){
if(err){
console.log(error);
}
else {
res.redirect('/notes');
}
})
});
But it is throwing error as "Object does not have save method". I don't want to use findByIdAndUpdate() as i am leaving this responsibility of generating id on mongo.
I don't understand what most of that code is doing. If I wanted to add a note to the document (I'm assuming newNote is defined elsewhere), I'd just do:
Model.findOne({'email':'test#test.com'},function(err, note){
note.notes.push(newNote);
note.save(function(err){});
});

how to tell when mongoosejs findOneAndUpdate method succeeds?

How can I tell when findOneAndUpdate successfully updates a document? huh variable always returns the same thing (whether id is in the database or not) and doc is always null.
var query = {id : id };
var huh = schemaModel.findOneAndUpdate(query, obj, function(doc) {
console.log(doc);
if(doc) {
callback(doc);
} else {
errback('');
}
}
);
console.log(huh);
You are only passing one parameter to the callback in your findOneAndUpdate query.
I think that your query succeeds, but doc will always come null when you successfully update the object as it is the first parameter which is the err.
Also, I do not see the code for your callback function, so I am just presuming that it can be accessed in the scope of your function.
var query = {id : id };
var huh = schemaModel.findOneAndUpdate(query, obj, function(err, doc) {
if(err) {
return "Error spotted!";
} else {
return "Found & Updated";
}
}
);
console.log(huh);
By returning those values, you are basically assigning them to the huh variable and it should log accordingly. It serves as a logging mechanism.

getting values from WriteResult mongo

I was trying to get familiar with the WriteResult object in mongo, but I can't access any of its values. The docs say the number of values inserted is stored in WriteResult.nInserted. Trying to access nInserted is crashing my server.
var readings = new Readings({
val1: parseInt(Data[0]),
val2: parseInt(Data[1]),
val3: parseInt(Data[2]),
val4: parseInt(Data[3]),
val5: parseInt(Data[4]),
val6: parseInt(Data[5]),
})
var result = readings.save(function (err, post){
if(err){return next(err)}
res.status(201).json(readings)
})
if(result.nInserted > 0){
console.log('wrote to database')
}
else{
console.log('could not write to database')
}
I know the data is being written to the database. I see it in the mongo shell.
The save method on a model instance doesn't return anything. All results are reported via the callback method, so you'd use something like this:
readings.save(function (err, doc, numberAffected){
if(err){return next(err)}
if (numberAffected > 0) {
console.log('updated an existing doc');
} else {
console.log('added a new doc');
}
res.status(201).json(doc)
})
Mongoose doesn't give you access to the full WriteResult, but as long as err is null you can rest assured the save succeeded and it's only a matter of whether an existing doc was updated or a new one was added. Because you're creating a new doc here, numberAffected will always be 0.