Mongoose update changes only one value - node.js

I want to update multiple values in mongo using mongoose, more accurate I want to update all the values that have a certain field smaller than a value and I am trying something like this:
var conditions = {Number: {$lt : 6000}};
var update = {$set: {closed_flag : true}};
var options = {};
UPUSTP.update(conditions, update, options, function(err, data) {
if (err) {
console.log(err.message);
return;
}
console.log(data);
});
If I try the same thing with an update I get 1000 values that were found but if I run update with the same conditions the last console.log outputs 1, so just one value was updated... I can figure out what the problem is...

To update multiples items with mongodb, yout options object should like this :
{ multi : true }
This option will tell MongoDB to update ALL elements that satisfy the query

Related

Update element of any particular index in an array in MongoDb using mongoose in Node.js

Hi I tried to update the element at a particular index in an array but I'm not able to update it. It is updating the entire array. Not able to figure out how to update any particular index. Also tried
{$set:{"Data.1:req.body}}
this is updating at 1st index but I don't want to hardcode the index value. It should take from frontend. Let say I have a schema in which I have Data who's type is array and default value is as shown below or anything in the same format.
Data: {
type: Array,
Default: ["0","1","0"]
}
Whenever I'll create a user then Data field will contain these default values, But now I want to update the value at any index (coming from frontend) of Data array of any user created.
I tried findByIdAndUpdate method but I don't know what to pass in set property. If I'm passing this {$set: req.body} and In postman I'm giving any value of Data then obviously it is updating Data array but I want to update value at any index which I'm passing from frontend, let say the index I'm passing is 2 then it should update the value of array at index 2, similarly I can pass any index from frontend how should I do that. What changes I have to make in {$set : } Thanks in advance.
Waiting for any help or suggestions. Thanks
It appears that you can solve this in backend logic if you are passing the index from the frontend.
You can dynamically specify the index, based on the input from the frontend, before you send a query.
const updateUserData = async (req, res) => {
const { index, user_id, new_value } = req.body;
try {
const update = {};
update[`Data.${index}`] = new_value;
const data = await Users.updateOne(
{ _id: user_id },
{ $set: update }
);
return res.status(200).json({ success: true });
} catch (error) {
return res.status(500).json({ success: false });
}
};

Loopback Find then update attribute or delete by id

Been trying to find samples usage for some of the static methods for a persistedModel in Loopback.
https://apidocs.strongloop.com/loopback/#persistedmodel-prototype-updateattribute
it just says:
persistedModel.updateAttributes(data, callback)
But how you I choose the which record I want to update? this is not working for me.
var order = Order.setId('whateverrecordId');
order.updateAttributes({name:'new name'},callback)
Loving loopback.. but their doc, sucks.. :(
You can use those on event listener like AfterSave
example:
Model.observe('after save', function(ctx, next) {
ctx.instance.updateAttribute(fieldname:'new value');
next();
});
1- What you did was right but i do not advise this method it's used for instance methods and generally to update fields like date for all the collection that you have so you don't need an id for it.
But you can try to make an array containing data to update containing also the ids and then make a comparison to fill in data for the ids that you have. (in #dosomething)
order.find().then(function(orders) {
orders.forEach(function(element) {
order.setId(element.id);
#DoSomething
order.updateAttribute({new: data}, function(err, instance) {
console.log(instance);
})
});
})
2- You can use updateAll to update one or many attribute.
PersistedModel.updateAll([where], data, callback)
var Updates = [{id : 1, name: name1}, ...]
Updates.forEach(function(element) {
order.updateAll({id : element.id}, {name :element.name}, function(err, count) {
if (err) {
console.error(err);
}
console.log(count); // number of data updated
})
})

Customize query according to the condition mongodb + node.js

I don't know whether I have too much expectation from mongodb, but I have a question here.
Is it possible to customize the query according to a boolean parameter? Firstly, I have looked https://docs.mongodb.com/manual/reference/operator/aggregation/cond/.
But didn't find an example where the condition is up to a another parameter.
Here let me clarify by an example;
Let assume I have a flag parameter. I want to execute two similar queries based on whether its value is true or false.
document is like;
{
"name" : "alex",
"age" : NumberInt(21)
}
{
"name" : "felix",
"age" : NumberInt(14)
}
To be able to look the condition I can break them into two different query as;
if(flag){
db.collection.find({age: "18"})
}else{
db.collection.find({age: "21"})
}
I am looking for something like this;
db.collection.aggregate([
{$cond: [flag,{$match: {age: "18"}} ,{$match: {age: "21"}}]}
])
But this throws an error which is not a surprise.
Is it possible to use $cond and execute two different query? Can a parameter pass in the $cond?
You can generate query first based on your condition then execute that query one time.
var query = {};
if(flag){
query.age = 18;
}else{
query.age = 21;
}
db.collection.find(query, function(err, result) {
if(err) {
// return error
}
console.log(result);
// return result
})

Getting error "pipeline element 3 is not an object error", while trying to find & update using aggregate

I am using node js mongodb driver & trying to update an object array inside an object array in a document.
The schema of the document collection is this :
What I Want :
For collection with order no = 1 & items.qty=2 & tax rate = 25, update the tax to "cst" & taxratetype to "flat".
What I Tried :
db.OrderInfo.aggregate(
{$match:{"orderno":"1"}},
{$unwind:'$items'},
{ $match: { 'items.qty' : 2}
},function(err,result1){
if(err){
throw(err);
}else{
indexes = result1[0].items.taxes.map(function(obj, index) {
if(obj.taxrate == 25) {
return index;
}
}).filter(isFinite);
var updateData = {};
updateData["items.$.taxes."+indexes[0]+".tax"]="cst";
updateData["items.$.taxes."+indexes[0]+".taxratetype"]="flat";
db.OrderInfo.update({ "orderno":"1",'items.qty': 2,'items.taxes.taxrate': 25 },{$set: updateData },function(err,result2){
console.log(result2);
});
}
});
Currently I am using db.eval to run this script from node but later will change it once I accomplish the same.
Getting this Error :
{"name":"MongoError","message":"Error: command failed: {\n\t\"ok\" :
0,\n\t\"errmsg\" : \"pipeline element 3 is not an
object\",\n\t\"code\" : 15942\n} : aggregate failed
:\n_getErrorWithCode#src/mongo/shell/utils.js:25:13\ndoassert#src/mongo/shell/assert.js:13:14\nassert.commandWorked#src/mongo/shell/assert.js:267:5\nDBCollection.prototype.aggregate#src/mongo/shell/collection.js:1312:5\n_funcs1#:1:31\n","ok":0,"errmsg":"Error:
command failed: {\n\t\"ok\" : 0,\n\t\"errmsg\" : \"pipeline element 3
is not an object\",\n\t\"code\" : 15942\n} : aggregate failed
:\n_getErrorWithCode#src/mongo/shell/utils.js:25:13\ndoassert#src/mongo/shell/assert.js:13:14\nassert.commandWorked#src/mongo/shell/assert.js:267:5\nDBCollection.prototype.aggregate#src/mongo/shell/collection.js:1312:5\n_funcs1#:1:31\n","code":139}
I know from this issue https://jira.mongodb.org/browse/SERVER-831
that I cannot use a direct update command & hence trying this workaround.
Any other approach for such updates is also fine with me.
EDIT :
As per answer given by #titi23, I had tried using [] also inside function.
It did not gave me any error but, my values also did not get updated.
Two problems in the query :
1) You are missing [] in the aggregate query.
2) The update method does not need the tax rate clause. It will find the nested document & the index from aggregate would serve the purpose in update.
Refer aggregate-definition for more info on how to use it.
Syntax - db.collection.aggregate(pipeline, options)
pipeline - array - A sequence of data aggregation operations or stages.
Try the following:-
db.OrderInfo.aggregate([
{$match:{"orderno":"1"}},
{$unwind:'$items'},
{ $match: { 'items.qty' : 2} }]).toArray(
function(err,result1){
if(err){
throw(err);
}
else{
console.log(result[0]); //See is there any record here
indexes = result1[0].items.taxes.map(function(obj, index) {
if(obj.taxrate == 25) {
return index;
}
}).filter(isFinite);
var updateData = {};
updateData["items.$.taxes."+indexes[0]+".tax"]="cst";
updateData["items.$.taxes."+indexes[0]+".taxratetype"]="flat";
db.OrderInfo.update({ "orderno":"1",'items.qty': 2}, /*Remove the tax rate clause from here..*/
{$set: updateData },function(err,result2){
console.log(result2);
});
}
});
It should not throw the error.
EDIT:- Do toArray() with the aggregate, see if it helps. Updated the query already.

Multiple updates in one document using mongoose

I want to update multiple values in a single document in one mongoose call. Is this possible?
I have something similar to this:
update = {$inc : { numShown : 1 }, $inc : { secondField.subField : 1 }};
options = {};
MyModel.findByIdAndUpdate(req._id, update, options, function(err){
if(err){ return console.error(err);}
}
It runs, but doesn't update anything.
You need to combine the two $inc values into a single object and quote the dotted key:
update = { $inc : { numShown : 1, 'secondField.subField' : 1 } };

Resources