Suppose that we have a shopping cart in the site, we have specified number of a good in database. Whenever the user wants to validate his/her cart and finalize it, I want to subtract the number of goods that the user purchased from total count of the product. How can I do that?
router.post('/done', (req, res) => {
// substract from the count
for (var i = 0; i < req.body.cart.length; i++){
Product.findOne({_id: req.body.cart[i]._id}).exec((err, result) => {
result.count = result.count - req.body.cart[i].count;
// update the value of result.count and save it on database
})
}
})
You just need to save, and also check for errors.
router.post('/done', (req, res) => {
// substract from the count
for (var i = 0; i < req.body.cart.length; i++){
Product.findOne({_id: req.body.cart[i]._id}).exec((err, result) => {
if(result)
{
result.count = result.count - req.body.cart[i].count;
result.save((err) => {
if (err) // do something
});
}
//If you don't find the product for some reason, do something
})
}
})
You can use mongoose's findOneAndUpdate() and $inc reference operator with a negative value to decrement the count.
Docs
The following update() operation uses the $inc operator to decrease the quantity field by 2 (i.e. increase by -2) and increase the "metrics.orders" field by 1:
db.products.update(
{ sku: "abc123" },
{ $inc: { quantity: -2, "metrics.orders": 1 } }
)
Making those changes
'use strict';
router.post('/done', (req, res) => {
let {cart} = req.body;
if (!Array.isArray(cart) || cart.length === 0) {
return res.status(400).send({
msg: 'Empty cart'
});
}
let updates = cart.map(item => {
return Product.findOneAndUpdate({
_id: item._id
}, {
$inc: {
count: -1 * item.count
}
}, {
upsert: false
});
});
Promise.all(updates).then(() => {
return res.status(200).send({
msg: 'inventory updated'
});
}).catch(err => {
console.log('err', err.stack);
return res.status(500).send({
msg: 'inventory update failed!'
});
});
});
Related
I am using Express node, MongoDB In this App.
Idea: send Post request contains an array of objects, => check if any object is existed before, => add the
not existed elements to the array in the document in one shot.
problem: Each time I sent a post request only one element is added. I have to repeat 3 times in order to add an array of 3 elements.
solution tried: before I used promise.all() nothing has been added. after I used promise.all only one element is added
code:
.post(cors.corsWithOptions, authenticate.verifyUser, (req, res, next) => {
let favstoAdd = req.body.favorites;
let user = req.user;
//check if the user have a favorites already and create favorites if it is not existed
var p1 = Favorites.findOne({ user: user._id })
.then((res_user) => {
if (res_user !== null) {
}
else {
Favorites.create({ user: user._id, favorites: [] });
}
});
//check if the dish Existed before in the favs and add them to the new filtered array
var altered_favstoAdd = [];
var p2 = favstoAdd.map((fav) => {
Favorites.findOne({ favorites: fav._id })
.then((dish) => {
if (dish == null) {
altered_favstoAdd.push(fav);
}
})
.catch((err) => { next(err) });
});
var p3 = promise.all([p1, p2]).then(values => {
//update favorite
for (let i = 0; i < altered_favstoAdd.length; i++) {
let alt_fav = altered_favstoAdd[i];
Favorites.update({ user: user._id }, { $push: { favorites: alt_fav } }, { new: true }, (err, resp) => {
if (err) { next(err); }
})
}
});
//respond with the favorite item
promise.all([p3]).then(
Favorites.findOne({ user: user._id })
.then((favorite) => { res.json(favorite); })
.catch((err) => { next(err) })
)
})
I think the problem is in the map function :
var p2 = favstoAdd.map((fav) => {
Favorites.findOne({ favorites: fav._id })
.then((dish) => {
if (dish == null) {
altered_favstoAdd.push(fav);
}
})
.catch((err) => { next(err) });
});
this function does not itereate over the whole array some thing is preventing it.
any Ideas??
can someone tell me how Can I response from this query, count() and list of products in one result??
Because at this moment its only return me Array with limit, i want count() without limit, of all products:
Array [ Object, Object, Object, Object, Object ]
router.get('/products', function (req, res) {
var size = parseInt(req.query.pageSize);
if (req.query.pageNumber == 1) {
var page = 0;
} else {
var page = parseInt(req.query.pageNumber) * req.query.pageSize - req.query.pageSize;
}
Product.count()
.exec(function (err, products) {
if (err) {
res.status(404).json({
message: 'Can not download this list'
})
} else {
Product.find().skip(page).limit(size)
.exec(function (err, products) {
if (err) {
res.status(404).json({
message: 'Can not download this list'
})
} else {
res.json(products);
}
})
}
})
});
you can do it in this way :
res.json({ "key1": value1, "key2": value2})
I cannot remove an element inside of an array that is a property of a MongoDB Model.
Please remember this is a NodeJS module mongooseJS and not the real MongoDB so functionalities are not the same..
GOAL: Delete an object from the statusLiked array. | I have also confirmed that the value of status.id is correct.
Model:
Const userSchema = new mongoose.Schema({
myStatus: Array,
statusLiked: Array,
)};
Delete:
1. Deletes the status(works). 2. Delete the status from User.statusLiked(no work).
exports.deleteStatus = (req, res, next) => {
var CurrentPost = req.body.statusid; // sends in the status.id
Status.remove({ _id: CurrentPost }, (err) => {
if (err) { return next(err); }
// vvvv this vvv
User.update( {id: req.user.id}, { $pullAll: {_id: CurrentPost }, function(err) { console.log('error: '+err) } });
req.flash('success', { msg: 'Status deleted.' });
res.redirect('/');
});
};
What happens: The specific status(object) is deleted from the database. But the status still remains in the User.statusLiked array.
What I want to happen: Status to be deleted from the User.statusLiked array and the status to be deleted from the database. Then, reload the page and display a notification.
I got it to work somehow. Working code:
exports.deleteStatus = (req, res, next) => {
var CurrUser = req.body.userid;
var CurrentPost = req.body.post;
Status.remove({ _id: CurrentPost }, (err) => {
if (err) { return next(err); }
console.log('meeee'+CurrentPost+'user: ' +CurrUser);
req.flash('success', { msg: 'Status deleted.' });
res.redirect('/');
});
User.update(
{ _id: new ObjectId(CurrUser)},
{ $pull: { myStatus : { _id : new ObjectId(CurrentPost) } } },
{ safe: true },
function (err, obj) {
console.log(err || obj);
});
};
I've Googled around and can't find any solid information on how to ignore duplicate errors when using bulk insert.
Here's the code I'm currently using:
MongoClient.connect(mongoURL, function(err, db) {
if(err) console.err(err)
let col = db.collection('user_ids')
let batch = col.initializeUnorderedBulkOp()
ids.forEach(function(id) {
batch.insert({ userid: id, used: false, group: argv.groupID })
})
batch.execute(function(err, result) {
if(err) {
console.error(new Error(err))
db.close()
}
// Do some work
db.close()
})
})
Is it possible? I've tried adding {continueOnError: true, safe: true} to bulk.insert(...) but that didn't work.
Any ideas?
An alternative is to use bulk.find().upsert().replaceOne() instead:
MongoClient.connect(mongoURL, function(err, db) {
if(err) console.err(err)
let col = db.collection('user_ids')
let batch = col.initializeUnorderedBulkOp()
ids.forEach(function(id) {
batch.find({ userid: id }).upsert().replaceOne({
userid: id,
used: false,
group: argv.groupID
});
});
batch.execute(function(err, result) {
if(err) {
console.error(new Error(err))
db.close()
}
// Do some work
db.close()
});
});
With the above, if a document matches the query { userid: id } it will be replaced with the new document, otherwise it will be created hence there are No duplicate key errors thrown.
For MongoDB server versions 3.2+, use bulkWrite as:
MongoClient.connect(mongoURL, function(err, db) {
if(err) console.err(err)
let col = db.collection('user_ids')
let ops = []
let counter = 0
ids.forEach(function(id) {
ops.push({
"replaceOne": {
"filter": { "userid": id },
"replacement": {
userid: id,
used: false,
group: argv.groupID
},
"upsert": true
}
})
counter++
if (counter % 500 === 0) {
col.bulkWrite(ops, function(err, r) {
// do something with result
db.close()
})
ops = []
}
})
if (counter % 500 !== 0) {
col.bulkWrite(ops, function(err, r) {
// do something with result
db.close()
}
}
})
In my application, I have an Model say it is Record, and a Record may have several Attachment which can be uploaded to the server.
Generally, when creating a Record with Attachment(files), I will upload and save the files first, then save the record, like this:
function createOrUpdateInfo(req, res, next) {
var record = req.body;
var attachmentIds = (record.files || []).map(function (a) {
return a.id;
});
var attachmentFilter = {
where: {
id: {
$in: attachmentIds || []
}
}
};
DB.sequelize.transaction(function (t) {
var pro;
if (record.id) {
//update
//update the basic information first
return Record.update(record, {
where: {
id: req.params.id
}, transaction: t
}).then(function (num, infos) {
//find the record just saved.
return Record.findById(req.params.id).then(function (record) {
//find the attachmens which have been saved
return Attachment.findAll(attachmentFilter).then(function (atts) {
//update the record, create the association.
return record.setFiles(atts, {transaction: t});
});
})
});
} else {
//save
return Record.create(record, {transaction: t}).then(function (record) {
return Attachment.findAll(attachmentFilter).then(function (atts) {
return record.setFiles(atts, {transaction: t});
});
});
}
}).then(function (result) {
Util.sendJson(res, result)
}).catch(function (err) {
next({message: err.message, code: 500});
});
}
As shown, there are too many nested callbacks when create or update a Record.
Is this can be fixed?
I've reorganized your code a bit. Hope it helps.
function createOrUpdateInfo(req, res, next) {
var record = req.body;
var attachmentIds = (record.files || []).map(function (a) {
return a.id;
});
var attachmentFilter = {
where: {
id: {
$in: attachmentIds || []
}
}
};
DB.sequelize.transaction(function (t) {
var pro;
return (function () {
if (record.id) {
//update
//update the basic information first
return Record.update(record, {
where: {
id: req.params.id
}, transaction: t
}).then(function (num, infos) {
//find the record just saved.
return Record.findById(req.params.id);
});
} else {
//save
return Record.create(record, {transaction: t});
}
}()).then(function () {
//find the attachmens which have been saved
return Attachment.findAll(attachmentFilter);
}).then(function (atts) {
//update the record, create the association.
return record.setFiles(atts, {transaction: t});
});
}).then(function (result) {
Util.sendJson(res, result)
}).catch(function (err) {
next({message: err.message, code: 500});
});
}