Passing parameters to the array updater method {$set: {"parameters": data}} - javascript

Comanda.findOneAndUpdate(id,{$set: {"orden.0.fondos.2.estadoitem": estado}}, {}, function(err, comanda)
I need to indirectly change that "2" in
$set: {"orden.0.fondos.2.estadoitem"
no matter what I do, i cant.. this will save my live =/..
i have tried everything, calling a var pos = 2; and then $set: {"orden.0.fondos.pos.estadoitem" also as a string pos= "2"; and nothing seems to work
thanks in advace

You can create $set field dynamically :
var set = { "$set": {} };
set.$set["orden.0.fondos." + pos + ".estadoitem"] = estado;
Comanda.findOneAndUpdate(id, set, {}, function(err, comanda) {
})

Seems orden is an array and so is fondos.
You could try
var doc = findOne({_id: id});
doc.orden[0].fondos[2] = 'anything you want';
doc.save((err,result)=>{})

Related

'$set' is empty even though it's not

I have a problem in updating a document in MongoDB...
in the params.sendingMethodPushTime and SmsTime i receive a new Date();
tried setting the $ set inside the update function itself and tried to use hardcoded values
userScheme.statics.updateAlertSendingTimes = function (params, cb) {
var query = {uId: params.uIds};
var set = {};
if (params.alertType) {
set['alertSendingTimes'] = {};
set['alertSendingTimes'][params.alertType] = {};
set['alertSendingTimes'][params.alertType]['push'] = params.sendingMethodPushTime;
set['alertSendingTimes'][params.alertType]['sms'] = params.sendingMethodSmsTime;
var update = {
'$set': set
}
this.update(query, update, {upsert: true}, cb);
} else {
cb(null)
}
};
$set should pass and MongoDB document is updated but instead, I get $set is empty etc
EDIT: my mongoose version is 4.13.4 and my node version is 6.16 and params.alertType is a string received dynamically (in my case it's '​1' or '2')
The issue was with the scheme... it was alerts and not alert

How to clone document to another collection? [duplicate]

My approach would be to get the document instance, and create a new one from the instance fields. I am sure there is a better way to do it.
You need to reset d1.isNew = true; as in:
Model.findById(yourid).exec(
function(err, doc) {
doc._id = mongoose.Types.ObjectId();
doc.isNew = true; //<--------------------IMPORTANT
doc.save(callback);
}
);
Can you clarify what you mean by "copy/clone"? Are you going trying to create a duplicate document in the database? Or are you just trying to have two vars in your program that have duplicate data?
If you just do:
Model.findById(yourid).exec(
function(err, doc) {
var x = doc;
Model.findById(yourid).exec(
function(err, doc2) {
var y = doc2;
// right now, x.name and y.name are the same
x.name = "name_x";
y.name = "name_y";
console.log(x.name); // prints "name_x"
console.log(y.name); // prints "name_y"
});
});
In this case, x and y will be two "copies" of the same document within your program.
Alternatively, if you wanted to insert a new copy of the doc into the database (though with a different _id I assume), that would look like this:
Model.findById(yourid).exec(
function(err, doc) {
var d1 = doc;
d1._id = /* set a new _id here */;
d1.isNew = true;
d1.save(callback);
}
);
Or if you're doing this from the outset, aka you created some document d1, you can just call save twice without setting the _id:
var d1 = new Model({ name: "John Doe", age: 54 });
d1.save(callback);
d1.save(callback);
There will now be two documents with differing _id's and all other fields identical in your database.
Does this clarify things a bit?
My two cents:
const doc = await DocModel.findById(id);
let obj = doc.toObject();
delete obj._id;
const docClone = new DocModel(obj);
await docClone.save();
So, a lot of these answers will work well for simple docs, but there could be an error case when you're trying to make a deep clone of complex documents.
If you have arrays of subdocs, for example, you can end up with duplicate _ids in your copied document, which can cause subtle bugs later.
To do a deep clone of a mongoose doc, I suggest trying something like:
//recursively remove _id fields
function cleanId(obj) {
if (Array.isArray(obj))
obj.forEach(cleanId);
else {
delete obj['_id'];
for (let key in obj)
if (typeof obj[key] == 'object')
cleanId(obj[key]);
}
}
let some_doc = await SomeModel.findOne({_id: some_id});
let new_doc_object = cleanId(some_doc.toObject());
let new_doc = new SomeModel(new_doc_object);
await new_doc.save();
This is going to be a pretty safe approach, and will ensure that every part of your object is cloned properly with newly generated _id fields on save.
The following code to clone documents:
Model.findById(yourid).exec(
function(err, doc) {
var newdoc = new Model(doc);
newdoc._id = mongoose.Types.ObjectId();
newdoc.save(callback);
}
);
For simply clone use this :
Context.findOne({
_id: context._id
})
.then(function(c) {
c._id = undefined;
c.name = context.name;
c.address = context.address;
c.created = Date.now();
return Context.create(c.toObject());
}).then(function(c) {
return res.json({
success: true,
context: context
});
}).catch(function(err) {
next(err, req, res);
});
const cloneDoc = (doc, model)=>{
const copyDoc = new Model({
...doc.toObject(),
_id: undefined,
});
copyDoc.isNew = true;
return copyDoc;
}
To copy a document into the same collection or different collection first get (query) the data and make a copy of the data. Afterwards remove the _id from the new list as you can't from the current data. This will allow you to insert a new record with new _id assigned from mongodb
change searchBy to what you are trying to find the document by.
change collectionA and collectionB to the name of the collection to create you copy to. Currently we are searching in collectionA and copying the data in collectionB
collectionA.find(searchBy).exec(function (err, doc) {
// create a new copy
let newDoc = { ...doc[0] }._doc;
// delete property from new copy (remove _id).
delete newDoc._id;
// insert copy into db
var newdoc = new collectionB(newDoc);
newdoc.save();
});
You can basically use .clone() to get a copy.
const cars = Cars.find();
const carsCopy = cars.clone();
await cars;
await carsCopy;
https://mongoosejs.com/docs/api.html#schema_Schema-clone

Javascript loop on a object

I want to loop on a object to find what's the object name who have the socket id, and then when it's found console.log it
Code:
getUsernameBySocketID: function(socketid) {
for(var User in Users.Obj) {
var u = Users.Obj[User];
if(u.socketID == socketid) {
return u.username;
}
}
},
EDIT:
User.Obj :
I add elements to user.obj with a function to create a new user:
Users.Obj[id] = new Users.User({username: username, socketID: socketID});
and Users.User contains :
User: function(data) {
this.username = data.username;
this.socketID = data.socketID;
},
but when I call the function and console.log it, it return nothing.
How can I solve that ? Thanks
Finally I've found my problem using #Watte's help
Users.Obj were just empty

parsing an array of JSON objects - null value preventing upsert

I am parsing an array of objects, and there's about 12 fields in each. I am doing this with two nested for(var i = 0; i < array.length; i++) functions, and ran into a null field several responses in.
I am expecting to get an embedded object, ... "caption": {"id":"some id", "text":"some text"}, but am instead getting a null in some cases. My schema does not require the field to have a value, but the document is getting kicked out.
How can I get around this? Would expect the null just to insert a blank value, but that is not the case. I am working within the Meteor.js framework, but the snippet I need help with below is just plain old javascript and a mongodb upsert. The error is on the caption.text line.
Meteor.methods({
'getMethod': function (var1, var2) {
check (var1, Number);
this.unblock();
var url = "https://www.url.com/"+var1+"/stuff?"+token+"&param="+var2;
var result = HTTP.call("GET", url);
if(result.statusCode===200) {
var aArray = JSON.parse(result.content).data;
for(var i = 0; i < aArray.length; i++){
var id = aArray[i].id;
var aItem = {
_id: aArray[i].id,
userId: aArray[i].user.id,
username: aArray[i].user.username,
created_time: parseInt(aArray[i].created_time),
type: aArray[i].type,
caption: aArray[i].caption.text, // THIS LINE IS THROWING THE ERROR !!
}
Collection.upsert(id, {$set: aItem}, {validationContext: 'upsertForm'}, function(error, result) {
if (error){
console.log("Error:", error);
return aArray;
}
});
}
} else {
console.log("Error: ", result.statusCode);
var errorJson = JSON.parse(result.content);
throw new Meteor.Error(result.statusCode, errorJson.error);
}
},
});
Use a ternary to check if there's a text property on the caption:
caption: (aArray[i].caption.text) ? aArray[i].caption.text : ''
Edit : If the caption property is questionable, then use the following:
caption: (aArray[i].caption) ? aArray[i].caption.text : ''
h/t RobG

How to convert values of an array into recursive field names of another variable in Javascript

I need to convert values from one Array variable into fields of another variable in Javascript.
My variable is
field = ["entries", "body"]
and it needs to become something like
req.body.entries.body
I tried doing something like
field.forEach(function(prop){
req.body[prop] = "...";
}
but that works only on req.body.entries and req.body.body. And I need it to go all the way to req.body.entries.body
I'm doing this to get the data from a form in a document field (named entries[body]), do some cleaning up on that data, and then pass it back to node.js as if it was the request that was originally made.
UPDATE
All I need to do is to basically
exports.sanitize = function(field){
// field = ["entry","body"];
return function(req, res, next){
val = getField(req, field); // val = "Some string with data"
val = some_process(val); // some_process is a function that cleans up the string
req.body.entry.body = val; // HOW TO TAKE entry.body from the field array???
next();
}
};
As you can see, all I want is to NOT hard code entry.body but take it from field array values that passes the name of the field for processing.
If you can think of a more elegant solution to do this, please, let me know.
Thanks!
This works:
var fields = [ "field1", "field2", "field3", "field4" ];
var obj = req.body;
fields.forEach(function(prop) {
obj[prop] = {};
obj = obj[prop];
});
You want
var obj = req.body;
for (var i=0; i<fields.length-1; i++)
obj = obj[fields[i]];
var prop = fields[i];
obj[prop] = cleanUp(obj[prop]);
This will work only if req.body.entries.body is already defined:
field = ["entries","body"];
var toeval="req.body";
field.forEach(function(prop){
toeval+="."+prop;
});
toeval+="=\"...\"";
eval(toeval);
I was able to accomplish this using recursion. Hope this helps!
var foo = {
bar: {}
};
var fields = ['foobar', 'barfoo'];
function setVar (currentVar, arr, counter) {
if (arr[counter] === undefined) {
return;
}
currentVar[arr[counter]] = {};
setVar(currentVar[arr[counter]], arr, counter + 1);
}
setVar(foo.bar, fields, 0);

Categories

Resources