I wanted to set up an auto incrementing ID on one of my collections (_id is too long). To do this I created a 'counters' collection as suggested in a number of posts including Mongos official site (below):
var mongoose = require('mongoose');
module.exports = mongoose.model('Counter', {
_id: String,
sequence_value: Number
});
I then inserted one counter with a seq value. Below is a function which is called when creating a new Item. The Logic to add the new item works and the query to get the counter value works to the extent that console.log(data.sequence_value); returns the sequence_value.
But I cannot then apply the sequence_value to the item creation logic by doing something like the following:
module.exports.newitem = function(req, res){
var nextId = Counter.findByIdAndUpdate(
{_id: 'productid'},
{ $inc: { incr: 1 } },
function (err, data) {
if(err){
console.log(err.stack || err.message)
} else{
console.log("successful")
}
console.log(data.sequence_value);
return data.sequence_value
});
var item = new Item();
item.itemId = nextId;
// Save the item that has been sent.
item.save();
// If adding the user is successful. Send back the user.
res.json(req.body);
};
The current disjointed version of the logic is below:
module.exports.newitem = function(req, res){
Counter.findByIdAndUpdate(
{_id: 'productid'},
{ $inc: { incr: 1 } },
function (err, data) {
if(err){
console.log(err.stack || err.message)
} else{
console.log("successful")
}
console.log(data.sequence_value);
});
var item = new Item();
item.itemId = "2000";
// Save the item that has been sent.
item.save();
// If adding the user is successful. Send back the user.
res.json(req.body);
};
Hopefully the above makes sense. Any help is very appreciated.
findByIdAndUpdate is an an asynchronous function. You should put your logic depending on its callback inside the callback itself, like so:
var nextId = Counter.findByIdAndUpdate(
{_id: 'productid'},
{ $inc: { incr: 1 } },
function (err, data) {
if(err){
console.log(err.stack || err.message)
} else{
console.log("successful")
}
console.log(data.sequence_value);
var item = new Item();
item.itemId = data.sequence_value;
// Save the item that has been sent.
item.save(); // arguably, your response would come in the .save() callback, if you care about whether that was successful or not.
// If adding the user is successful. Send back the user.
res.json(req.body);
});
};
Thought I would put what I ended up with using Paul's answer.
module.exports.newitem = function(req, res){
Counter.findByIdAndUpdate(
{_id: 'productid'},
{ $inc: { sequence_value: 1 } },
{ "upsert": true },
function (err, data) {
if(err){
console.log(err.stack || err.message)
} else{
var item = new Item();
item.itemId = data.sequence_value;
...
// Save the item that has been sent.
item.save();
// If adding the user is successful. Send back the user.
res.json(req.body);
console.log("successful")
}
});
};
Related
I'm fairly new to nodejs and I'm doing a full stack developer challenge from devchallenges.io (Shoppingify). Below, I'm trying to add a new item. However, there's a slight delay between the return value from the request and the actual value in the database. The value updates straight away which is great however, the return value in the request is the previous value rather than being the current quantity value in the database.
// #route POST api/category
// #desc Add category and items
// #access Private
router.post(
'/',
[
check('name', 'Name is required').notEmpty(),
check('category', 'Category is required').notEmpty(),
],
auth,
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({
errors: errors.array(),
});
}
const { name, note, image, category } = req.body;
const itemObject = { name, note, image, category };
try {
const categoryItem = await Category.find({
user: req.user.id,
});
// check if category object are empty
if (categoryItem.length === 0) {
const newCat = new Category({
user: req.user.id,
name: category,
items: itemObject,
});
await newCat.save();
res.json(categoryItem);
} else if (categoryItem.length !== 0) {
// check if category name already exists
categoryItem.map(async (cat) => {
if (cat.name.toLowerCase() === category.toLowerCase()) {
cat.items.push(itemObject);
await cat.save();
res.json(categoryItem);
} else {
// create new category
const newCat = new Category({
user: req.user.id,
name: category,
items: itemObject,
});
await newCat.save();
res.json(categoryItem);
}
});
}
} catch (error) {
console.error(error.message);
res.status(500).send('Server Error');
}
}
);
You are not returning the correct item…
Return the result of newcat.save()
Or try a new findById if newCat is not the correct object to return
I have JSON with 10000 unique records and I need to add another field with a unique value to every record. How do I add that?
[
{
_id: "5fffd08e62575323d40fca6f",
wardName: "CIC",
region: "ABC",
location: "AAA",
specialism: "CSR",
__v: 0
},
.
.
.
]
The JSON is stored in variable showWard. How do I add an action field in my JSON with value = './wardName' where wardName is already a field in my JSON?
This is my current code:
app.get('/wards', function (req, res) {
Ward.find({}, function (err, showWard) {
if (err) { console.log(err); return; }
return res.send(showWard);
});
});
Using a .map()? I don't know the logic for determinate the gender, but in Ward.find() callback you can add a thing like that:
app.get('/wards', function (req, res) {
Ward.find({}, function (err, showWard) {
if (err) { console.log(err); return; }
const newShowWard = showWard.map(ward => {
ward.gender = "BOH";
return ward;
})
return res.send(newShowWard);
});
});
i am working on an Ionic-1 + nodejs + angular application. My mongoDb findOneAndUpdate() function returns true on each call even the first call updates database.
nodejs:
app.post('/booking', function (req, res) {
var collection = req.db.get('restaurant');
var id = req.body.id;
var status = req.body.status;
collection.findOneAndUpdate({status: status, id: id},{$set:{status:"booked"}}, function (e, doc) {
console.log(id, status);
if (e) {
console.log(e);
}
else if(!doc) {
res.send(false);
}
else {
res.send(true);
}
});
});
controller.js
$scope.bookMe = function(id){
var Obj = {status: "yes", id: id};
myService.booking(Obj).success(function(res){
console.log(Obj, "Checking status")
console.log(res);
if (res == true) {
var alertPopup = $ionicPopup.alert({
title: 'Booking Confirm',
template: 'Thanks For Booking'
});
}
else{
var alertPopup = $ionicPopup.alert({
title: 'Error',
template: ' Not available'
});
}
})
};
where i am doing wrong. my DB gets updated but it returns true always on next call.
The documentation about findOneAndUpdate says :
Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed.
So it's regular behavior you got a doc.
Note:
Since you are checking availability status="yes", Better hard code, instead of getting it from request query/data.
Change the response according to your requirement res.send(true)/ res.send(false).
Following code will work
app.post('/booking', function (req, res) {
var collection = req.db.get('restaurant');
collection.findOneAndUpdate({
status: "yes",
_id: req.body.id
}, {
$set: {
status: "booked"
}
}, function (err, result) {
//Error handling
if (err) {
return res.status(500).send('Something broke!');
}
//Send response based on the required
if (result.hasOwnProperty("value") &&
result.value !== null) {
res.send(true);
} else {
res.send(false);
}
});
});
I'm new to nodejs and trying to write a function to update and object on mongodb.
Here is my fundtion that is under routs/rates.js. Briefly, the function is called whenever a button/link called "like" is clicked and it should update the total number of like this item has recieved. Item is an object in my mongodb.
router.put('/update_likes', function (req, res) {
var sessionId = req.sessionID;
var queryId = req.body.queryId;
var item = req.body.item;
var itemId= req.body.itemId;
var commentsNum= req.body.commentsNum;
var category= req.body.category;
var find_condition = {
'item': item,
'sessionId': req.sessionID,
'category': category,
'commentsNum': commentsNum
};
var update_callback = function (err, item_obj) {
if (err)
return console.log('An error occurred: ', err);
var update = {
$inc: { 'totalLikes': 1 },
$push: {
'likes': {
'itemId': itemID,
'sequence': item_obj.totalLikes + 1
}
}
};
Query.update(find_condition, update, function (err) {
if (err)
return console.log('[UPDATE] ', err);
});
}
Query.findOne(find_condition, update_callback);
res.sendStatus(200);});
Using the function above, gives me an error that totalLikes is undefined in line 15. What I understant is that I cannot use item_obj inside var update = {}, but I actually don't know how to solve this issue in another way.
Any hints? or suggested enhancements to the code?
I'm new to expressJS and i'm wondering what is the best way to requery the database (mongo in my case) to get all the records after one is added.
exports.get = function (db) {
return function (req, res) {
var collection = db.get('notes');
collection.find({}, {}, function (e, docs) {
res.send(docs);
});
};
};
exports.create = function (db) {
return function (req, res) {
var title = req.body.title;
var note = req.body.note;
var collection = db.get('notes');
// Insert/update the note
collection.insert(
{
"title": title,
"note": note
},
function (err, doc) {
// If it failed, return error
if (err) {
res.send("There was a problem adding the information to the database. Error: "+err);
} else {
//res.redirect('/');
//res.json(db.get('notes'));
// WHAT IS THE BEST THING TO DO HERE TO GET ALL THE RECORDS INCLUDING THE ONE I'VE JUST ADDED?
exports.get(db);
}
}
);
}
};
I would replace
exports.get(db);
for
collection.find({}, {}, function (e, docs) {
res.send(docs);
});
The reason is that you are invoking this in the callback, AFTER the record has been inserted
Your exports.get function return a function, a kind of middleware I see.
Repplace
exports.get(db);
by
exports.get(db)();