express/mongoose update query - node.js

I having problem wrapping my head around updating multiple values in my mongoDB using mongooseJS and ExpressJS.
Let say I submit an array of 2 or more objects from my frontend to "express routing" and there I get the req.body parameters to fetch it. My req.body looks like this:
[articles:
{ article: {
_id: '564209c66c23d5d20c37bd84',
quantity: 25,
},
{ article: {
_id: '564209c66c23d5d20c37bd83',
quantity: 51,
},
}]
I then need to loop? to find the specific article in the db to update and when that article is found I want to update the "quantity" value from the frontend to the correct article in db.
var id = [];
var body = {};
for (var i = req.body.length - 1; i >= 0; i--) {
id.push(req.body[i].article._id);
body[i] = req.body[i].article.quantity;
};
Articles.update(
{ _id: {$in: id} },
{ $set: {quantity: body[0].article.quantity} },
{multi: true},
function(err, response){
if(err)
console.log(err);
console.log(response);
});
The problem with this code is that I put in the first quantity value for all articles and I want it to be the correct one from the frontend. It feels like I'm on the right path but i pretty new to mongoDB and express so if there is a better solution or even a solution let me know.

Grahlie,
If you are having issues with queries, it's sometimes useful to test queries from the mongodb shell itself to workout the logic.
If your article documents are structured as such:
{
_id: ObjectId("564209c66c23d5d20c37bd84"),
quantity: 25
}
{
_id: ObjectId("564209c66c23d5d20c37bd83"),
quantity: 51
}
If you want to update the quantity of a unique document based on it's _id then you could so with this query.
db.articles.update(
{"_id": "564209c66c23d5d20c37bd84"},
{$set : { "quantity" : 25}}
)
If you wanted to update multiple documents with the same quantity you could use $in, but that's not what you want to do. You want to loop through your req.body array and update the quantity of each article.
So your code would be as such:
var articles = req.body;
var updateArticle = function(article) {
Articles.update(
{_id:article._id},
{$set:{ quantity: article.quantity}},
function(err, article){
...
);
}
for(var i = 0, n = articles.length; i < n; i++){
updateArticle(articles.[i].article);
}

Related

Deleting relational data in MongoDB - Removing specific element from Array

I have a collection of users and a collection of articles. A user holds multiple articles in an array. Now I'm trying to delete an article from a User's array of articles in MongoDB. So far I have
exports.delete = function(req, res, next) {
const articleId = req.params.id;
Article.findOneAndRemove({_id: articleId})
.then((deletedArticle)=> {
const authorId = deletedArticle.author;
console.log("AUTHOR:"+authorId);
User.update( { _id: authorId }, { $pull: { articles: [ _id: deletedArticle.id ] } } )
res.status(204).send(deletedArticle)
})
.catch(next);
}
this does delete this article itself, however, not the reference to the article saved in the array the User object holds. What am I doing wrong here?
Try changing the square brackets in your query to curly:
User.update( { _id: authorId }, { $pull: { articles: { _id: deletedArticle.id } } } )
This would obviously require that the _id in the articles array is the same as the article collection, which depends on how you populate the array (I have a feeling you are doing that part right, but just wanted to mention that possibility up front).

Mongoose: How to push in nested array? [duplicate]

This question already has answers here:
Updating a Nested Array with MongoDB
(2 answers)
Closed 3 years ago.
I am very new to NoSQL world. Here the screenshot of my Mongoose schema.
I need to insert,update and delete document to/from vehicles array.
What I have tried so far:
Add: (Working)
Companies.findOne({'mobile' : givenMobileNumber, 'VehicleGroups.vehicle_group_id' : vehicleGroupId}, (err, res) => {
if( err || res == null) {
callback(err, res);
}else{
var len = res.VehicleGroups.length;
for(var i=0; i<len; i++)
{
if(res.VehicleGroups[i].vehicle_group_id == vehicleGroupId)
res.VehicleGroups[i].vehicles.push(data);
}
res.save(callback);
}
})
Delete: (Working)
Companies.findOneAndUpdate({ mobile : givenMobileNumber, 'VehicleGroups.vehicle_group_id' : vehicleGroupId},
{ $pull : {'VehicleGroups.$.vehicles' : { 'vehicle_id' : vehicleId} } }, callback);
Still working to update data. Is my approach valid?
Thanks
You can consider setting up separate schemas for your VehicleGroups and vehicles and reference them through ObjectId in your Companies schema:
VehicleGroups: [{
_id: { type: Schema.Types.ObjectId, ref: 'vehicleGroup' },
// All other properties here
vehicles: [{ type: Schema.Types.ObjectId, ref: 'vehicle' }]
}]
Adding a new document to theVehicleGroup schema would then go something like this:
const newVehicleGroup = new VehicleGroup({
name: 'New Vehicle',
// Set all other fields
})
And adding it to the Companies schema:
Companies.findOneAndUpdate({
mobile : givenMobileNumber, 'VehicleGroups.vehicle_group_id' : vehicleGroupId,
{ $push: { vehicleGroups: newVehicleGroup._id } }
})
Since you reference vehicles and VehicleGroups by ObjectId, all you have to do to update that reference is to update the document in the respective collection.
However, if you delete a document you will need to remove its reference from the respective array in the Companies collection.
See if this approach makes it a little easier!

Mongoose saving many IDs in one record

exports.save = (req, res)=>{
console.log(req.body)
let account_type_data = new AccountType()
account_type_data.account_name = req.body.account_name
account_type_data.account_type = req.body.account_type
account_type_data.account_bin = req.body.account_bin
account_type_data.account_charges = []
let charge_name = req.body.account_charge_name
for(var x = 0; x < charge_name.length; x++){
let push_value = {
charge : req.body.account_charge_value[x],
name : req.body.account_charge_name[x],
order : req.body.account_charge_order[x],
reoccurence : req.body.account_charge_reoccurence[x]
}
account_type_data.account_charges.push(push_value)
}
console.log(account_type_data)
account_type_data.save((err)=>{
if(err) return res.render('settings/all', { validated : req.body, csrfToken: req.csrfToken(), error : err})
res.render('settings/all')
})
}
This is my code but when i run it I dont get what I expect to get
{ account_bin: '50',
account_type: '1D',
account_name: 'Daily contribution regular',
_id: 5a596d43db4788ddb296e41a,
status: 0,
account_charges:
[ { name: 'Opening',
order: 0,
reoccurence: true,
_id: 5a596d43db4788ddb296e41b,
charge: 1000 }]
}
I expect to get without the _id in the account_charges. Please can someone help me to find out why an _id is printed in the account_charges or what i am doing wrong
Here account_charges is an array of subdocuments in AccountType.
For every subdoc Mongoose will insert an auto generated __id which can be useful for querying like parent.children.id(_id);
This behaviour of adding __id to subdocs can be turned off using { _id : false } when defining schema.
Stop Mongoose from creating _id property for sub-document array items

How to aggregate and group in mongoose

I have lot of accounts with each of them having an employee assigned. I want to find the number of accounts of each employee. How do I do this task using aggregate of mongoose(mongodb). I am familiar with other functions of mongoose and able to achieve with following code
exports.accountsOfEachEmployee = function(req, res) {
Account.find({active:true}).exec(function(err, accounts){
if (err || !accounts) res.status(400).send({
message: 'could not retrieve accounts from database'
});
var accountsOfEachEmployee = {};
for (var i = 0; i < accounts.length; i++) {
if(accountsOfEachEmployee[order[i].employee]) {
accountsOfEachEmployee[order[i].employee] = 1;
} else {
accountsOfEachEmployee[order[i].employee]++;
}
}
res.json(accountsOfEachEmployee);
});
};
Is using aggregate faster? How does grouping and aggregation work in mongoose(mongodb). Following is my schema of accounts
var AccountSchema = new Schema({
active: {
type : Boolean,
default: false
},
employee: {
type: Schema.ObjectId,
ref: 'Employee'
},
});
Aggregation is an faster than map reduce to get results in mongodb for simple queries. I am able to complete the above query with result and then group, count of mongodb. Following is the query I used later
Order.aggregate({$match: {active: true }},
{$group: {_id:'$employee', numberOfOrders: {$sum:1}}}, function(err, orders) {
res.json(orders);
});
Query is executed in 2 parts. First part is getting all the results which are active and then group them based on the value of employee along with getting a new field numberofOrders which is number of number of documents in each group formed when we grouped based on employee.

Updating an array item using NodeJS, MongoDB & Monk

I have a data set like this:
{
name : 'Doc Name',
photos: [
{
name: 'photo1',
url: 'http://.....'
},
{
name: 'photo2',
url: 'http://......'
}
],
etc ...
Using Monk https://github.com/LearnBoost/monk how do I update photo2? I can use an index as I am iterating over the fields at the moment.
My current attempt below gives me an error, and I can't use a variable for the JSON selector (as in the index).
collection.update({_id: data._id}, {photos[i].data: filename}, function(err, updatedata) {
});
Updating items at a position in an array can be done using the positional $ operator
collection.update(
{ _id: data.id, "photos.name": "photo2" },
{ $set: { "photos.$.data": "yourdata" } }
)
So I found a solution to my problem but there may be some better options and I will leave it unanswered. But for anyone else with the same issue this is what I did:
I extracted the MongoDB document as an object in Node.js, manipulated the document, and then replaced the entire array in a single update statement. For example here is some pseudo code:
collection.find({id: 1}, function(err, doc){
for(i=0; i< doc.array.length; i++) {
//do what you gotta do
doc.array[i].property = 'new value';
}
collection.update({id: 1}, {$set : {"doc.array": doc.array}}, function(err,doc){
console.log(err);
}
})

Resources