Find one element, use data, then delete it - javascript

In my node.js application I'm currently implementing a "Remember Me" functionality. Everything works quite well so far, but I have a problem with mongoose. What I want to do: I have a model named Token with this schema:
var TokenSchema = mongoose.Schema({
token: { type: String },
uid: { type: Schema.Types.ObjectId, ref: 'User' }
});
This is simply a little collection that maps cookie tokens to a UserId. Then I have this function here:
function consumeRememberMeToken(token, fn) {
Token
.findOne({ 'token': token }, (err, result) => {
return (result===null)?fn(null, null):fn(null, result.uid);
})
.remove();
}
What it should do, is this: find the uid for a given token string and return it (if there is a result). But this function should also delete the entry right after returning the uid.
At the moment, the uid from the found token result gets returned properly, but it (the result Token) does not get deleted from the collection with the above code. I don't understand how to remove it right after getting it and using the retrieved uid. I'm completely new to functional programming and I don't understand how and where to delete the token.

You can try db.collection.findOneAndDelete It deletes the document and returns the deleted data, quite the reverse of what you are saying but basically serves your purpose. here are the details.
Also here is the mongoose representation of the same.

Token.findOne({ 'token': token }, (err, result) => {
if(err || !result) return fn(err || "error", null);
else{
var uid = result.uid;
result.remove(function(){
return fn(null, uid);
});
}
})

Related

Mongoose collection.update does not update the document

I am having an issue using Mongoose's update function. Basically the document I am trying to modify is not getting updated.
Here is the code:
const user = 'Joe Bloggs'
const salt = await bcrypt.genSalt()
const pwStr = 'simplepassword'
const hashedPassword = await bcrypt.hash(pwStr, salt)
User.update({user_name: user }, { $set: { password: hashedPassword }}, function(err, doc) {
if (err) console.log('Error ', err);
console.log('Updated Doc -> ', doc); // returns un-updated doc
});
As you can see there is not much to it. The only thing I thought could be causing an issue was the bcrypt functions, but they seem to be working and hashedPassword logs out fine.
The callback logs the document, but it is not updated and when I check it in the Mongo shell it is indeed not updated.
I previously tried findOneAndUpdate but it appears that has been deprecated.
So, I tried findOne, but this also failed to update the document. Here is the basic code which uses save on the found user instead.
User.findOne({user_name: user}).then(async function(user) {
user.password = 'easypassword';
await user.save();
}
});
I tried using update in the shell using the same { $set: {...}} syntax and it works.
If anyone can tell me why this operation isn't working when I try to do it using the Mongoose functions I'd much appreciate it. Thanks in advance!
EDIT
I have tried the suggested code below:
const res = await User.updateOne([filter], [query]);
This returns the following when res is logged out:
{ acknowledged: false }
This appears in MongoDB documentation to relate to a "write concern" setting, but I have no idea where to go with it from there.
update is what is actually deprecated.
findOneAndUpdate, like other mongoose update methods, it returns the un-updated object by default. Setting the option new to true will return the updated doc.
Another option would updateOne;
User.findOneAndUpdate(
{ user_name: user },
{ $set: { password: hashedPassword } },
{ new: true },
function (err, doc) {
if (err) console.log("Error ", err);
console.log("Updated Doc -> ", doc);
}
);

PG-Promise Proc Erroring Out with Unknown Parameter Type

We are attempting to write a PostgreSQL Procedure to insert data into a table. We have created the procedure and ran said procedure with the variables below and it inserts just fine. However, when we try to use pg-promise with our express server, our string parameters are being read as unknown. When we iterate over the post body, we see that each parameter is reading as the type we expect to go in, and PostgreSQL is reading integer correctly, but it isn't reading string correctly. I've attempted to use the as.text function and it sends in the parameter value as "''" but that still reads as unknown. Is there something we are missing to successfully post the data?
let createInspection = async (req, res, next) => {
try {
let params = [];
for (let prop in req.body) {
console.log(typeof req.body[prop]);
params.push(req.body[prop]);
}
console.log(params)
let data = await db.proc('Inspections_Create', params);
res.status(200)
.json({
status: 'success',
data: data,
message: 'Inserted Inspection'
});
}
catch (error) {
return next(error);
}
}

Mongoose find search if statement error using expressjs

This is a URL shorten-er project
app.get('/:url', (req,res) => {
Url.find({userUrl:req.params.url},(err,doc)=>{ //finds if there is a link in the database
if(err){
console.error(err)
}else if(doc[0].userUrl==req.params.url) { // there is an error in this line if a new link is passed in the params.url, or else if the link existed then there is no issue
console.log('hi')
}else { // if no link is not reaching?
const url = new Url({
userUrl:req.params.url
})
url.save();
}
})
})
if i have a link in my database example google.com , it does give me output of hi , but when i put other link it gives me a 'property userUrl undefined' error in the first else if statement.
my schema is like this let urlsSchema = new Schema({
userUrl:String,
shortUrl: {
type: String,
'default': shortid.generate
}
})const Url = mongoose.model('urls',urlsSchema);`
i think i need to write it in a way where, if you cant find it in the database then create a new url document.. not working tho
`
The main problem is that find only throws an error if either the request is corrupted or the database connection does not work. If no data was found, it will not return an error but rather an empty doc array. If you then access doc[0], it will return undefined, and undefined has no userUrl. A possible solution would be to check if the doc array has a first document:
Url.find({ userUrl: req.params.url }, (err, doc) => {
if(err){
return console.error(err);
if(doc[0]){
//Exists already
console.log(doc[0]);
} else {
//Doesnt exist yet, so create a new one:
const url = new Url({
userUrl: req.params.url
})
url.save();
}
});
Note that you should rather use findOne to check for existence.

Mongoose & MongoDB $Push is correctly updating array of strings, while emptying and refusing to update second array of numbers

I am trying to update an array within a MongoDB collection
It successfully updates when fed the entire array, but the array of numbers breaks and loses all of its values when I use a $Push operation. The array of strings remains intact and successfully updates.
I am trying to update this
var transactionSchema = new Schema({
items: [String],
itemsPrice: [Number],
});
With a single or multiple from value from this.
var itemSchema = new Schema({
itemName: String,
itemPrice: Number,
});
This works when I update using this method
module.exports.updateTransactionById = function (req, res, next) {
Transaction.findOneAndUpdate({_id: req.params.id}, req.body,
{ new: true }, function(err, transaction) {
if (err) return next(err);
if (!transaction) res.status(404).send("No transaction item with that ID!")
return res.status(200).send(transaction);
});
}
// update empty transaction
// RESULT: transaction: {_id=01, items=[a], itemsPrice=[3]}
// update any transaction with some array
// RESULT: transaction: {_id=01, items=[a,b,c], itemsPrice=[1,2,4]}
However, I have to send the entire pre-existing array with each update, which means I would need to query the transactions collection with a GET request before updating it, and that seems unnecessary.
I'm using the $Push method in Mongoose and it doesn't work.
module.exports.updatePushTransactionById = function (req, res, next) {
Transaction.findOneAndUpdate({_id: req.params.id}, { $push: req.body },
{ new: true }, function(err, transaction) {
if (err) return next(err);
if (!transaction) res.status(404).send("No transaction item with that ID!")
return res.status(200).send(transaction);
});
}
// Try updating an empty transaction
//RESULT: transaction: {_id: 01, items=[a], itemsPrice=[]}
// increment subsequent updates
//Result: transaction: {_id: 01, items=[a,b,c,d], itemsPrice=[]}
// Try updating an existing transaction that looks like:
// transaction: {_id: 01, items=[a,b,c,d], itemsPrice=[2,3,4,5]}
// Run push update
//Result: transaction: {_id:01, items=[a,b,c,d,e], itemsPrice=[]
The request body seems to be valid. The casting seems okay, since it accepts the same exact request for the findOneAndUpdate method WITHOUT using a $Push
If this doesn't make sense, here's what I'm trying to accomplish:
A user will click a button to contact the DB and query for the price of an item. The name and price of the item will be fed into a transaction DB. I know holding the details of the transaction in an array is not good, but bear with me.
These are the fetch calls I am using:
GET the price of the item.
function getMenuItemFromDatabase(target) {
var url = '/menus/' + target.id;
return fetch(url, {
method: 'GET'
}).then(function(res){
if(!res.ok) console.log("Error");
else return res.json().then(function(result){
var returnedItem = JSON.parse(result)
return returnedItem[0];
}).catch(function(err){
console.log(err);
throw err;
});
});
}
PUT (by pushing into array) the name and price
function updateTransaction(target){
getMenuItemFromDatabase(target).then(function(menuItem) {
var data = {
items:[menuItem.itemName],
itemsPrice:[menuItem.itemPrice]
}
var url = '/transactions/' + localStorage.transactionID;
fetch(url, {
headers:{
'Content-Type': 'application/json'
},
method: 'PUT',
body: JSON.stringify(data)
}).then(function(res){
if (!res.ok) alert("ERROR!")
else return res.json().then(function(response){
}).catch(function(err) {
console.log(err);
throw(err);
});
});
});
}
I'm pretty confused why this is happening. I've tried looking over the code and playing with the console.log dump in various places, but I'm stuck at this point. I would appreciate any input as to what I must be missing here.
console.log(typeof(req.body.items[0])); // String
console.log(typeof(req.body.itemsPrice[0])); // Number ... so it should work??
I have tried pushing req.body.itemsPrice, req.body.itemsPrice[0], req.body, but the itemsPrice array refuses to update for me.
This is a sample req.body that gets logged by the api
{ items: [ 'Pizza' ], itemsPrice: [ 5.25 ] }
I tried to construct the push query like this:
{ $push: { itemsPrice: req.body.itemsPrice, items: req.body.items} }

return response result of following mongoose's schema

I've been using node (express) with mongoose for a while but I have little clue about mongoose's schema. What I know is it throw you an error and prevent you to do any db operation if the request object (like req.body.firstName) you pass is not exist in the schema.
How can I return my api result according the schema? for example I have a schema like this
const UserSchema = mongoose.Schema({
first: {
type: String
},
last: {
type: String
}
}
module.exports.getAllUsers = (callback) => {
User.find({}, (err,result => {
console.log(result)
})
}
I might not get first and last property in my array, I get whatever data that store in the users collection.
Does it means every response I have to manually do
res.json({
first,
last
})
I'm looking an option to return response that will follow mongoose's schema.

Categories

Resources