I'm working with sequelize and want to query my database using the following code:
models.user.findOne({ where: {email: req.body.email} }, (err, existingUser) => {
.... More code
}
But the code block wont run so i read the docs and the only example they give uses the following structure:
models.user.findOne({ where: {title: 'aProject'} }).then(project => {
.... Code
})
Did i do something wrong with the first example or am i just unable to use that structure?
Sequelize.js uses promises. When you use findOne, as an example, a promise is returned. So try the following:
models.user.findOne({
where: {
email: req.body.email
}).then(existingUser => {
//Do something
}).catch(err => {
//Do something with error
});
Sequelize>=1.7 query return a promise , to resolve it you need to use "then"
nb: you can use the model directly from the declaration instead of "models.user" like this:
const Userdb = sequelize.define('userdb', {
id : {
primaryKey: true,
autoIncrement:true,
allowNull:false,
type: Sequelize.INTEGER
},
email: {
type: Sequelize.STRING,
allowNull:false,
validation:{
isEmail:true
},
username: {
type: Sequelize.STRING,
allowNull:false,
min:6,
max:25,
notEmpty:true,
}
}
and to get a user by it's email you can do this :
Userdb.findOne({
where: {
email: req.body.email
}
}).then((result)=>{
if(results) // there is one user
{
// do something with resutls
}else{
// no user with that mail
}
})
Related
So I am learning CRUD for a school project and I followed a tutorial that was really useful. However, when I completed it I noticed that when there are no more quotes to update, it still updates quotes. How can I change this so that it will stop updating quotes that arent even there?
app.put('/quotes', (req, res) => {
quoteCollection.findOneAndUpdate(
{ name: 'Yoda' },
{
$set: {
name: req.body.name,
quote: req.body.quote
}
},
{upsert: true}
)
.then(result => {
//The if block that i am trying
if (result.deletedCount === 0) {
return res.json('No quote to delete')
}
})
.catch(error => console.error(error))
})
Why are you passing {name: "Yoda}? This route is supposed to only update the quote with "Yoda" as its name? If not, then you need to grab from the request object the quote that should be updated.
I tried to create a different version, based on the assumption that the quote that should be updated will come from the req.body:
app.put("/quotes", async (req, res) => {
//Grab the name/id/identifier for the quote you want to update from the body
const query = req.body.name;
// Try to update the document on the database
try {
const result = await quoteCollection.findOneAndUpdate(
query,
{
name: req.body.name,
quote: req.body.quote,
},
{
upsert: true,
new: true,
}
);
// If it worked, it will return the updated quote
res.status(200).json({
status: 200,
data: {
result,
},
});
} catch (err) {
res.status(400).json({
status: 400,
message: "Something went wrong",
});
}
});
I have a REST API built with Node JS and I'm currently using MongoDB as my database. I want to prevent the users from deleting another user's products and for this I checked if the userId from the decoded token is the same as the product userId.
Product schema
const mongoose = require("mongoose");
const productSchema = mongoose.Schema(
{
_id: mongoose.Schema.Types.ObjectId,
userId: mongoose.Schema.Types.ObjectId,
name: { type: String, required: true },
price: { type: Number, required: true },
productImage: { type: String, required: false },
category: {
type: mongoose.Schema.Types.ObjectId,
ref: "Category",
required: true
},
gender: { type: String, required: true }
},
{ timestamps: { createdAt: "created_at" } }
);
module.exports = mongoose.model("Product", productSchema);
The delete product method:
const id = req.params.productId;
Product.findById({ _id: id }).then((product) => {
if (product.userId != req.user._id) {
return res.status(401).json("Not authorized");
} else {
Product.deleteOne({ _id: id })
.exec()
.then(() => {
return res.status(200).json({
message: "Product deleted succesfully",
});
})
.catch((err) => {
console.log(err);
return res.status(500).json({
error: err,
});
});
}
});
};
As you guys see first I'm searching executing the findByID method to access the userId property of the product, then I'm comparing the userId from the response with the userId from the decoded token.
I don't think my method is very efficient since it's running both findById and deleteOne methods.
Can you help me with finding a better solution for this?
as Guy Incognito mentioned, what you are trying to do is an OK thing and you may want to keep it this way in case you want to send a 404 status stating the product they are trying to remove does not exist.
however, if you are trying to do it with only one request
Product.deleteOne({ _id: id, userId: req.user._id })
hope it helps!
This is my controller to update put user data. The controller accepts up to 4 values. I would like to do so if I send only a name to this route, This will change only the name and the rest will remain unchanged. (it will not be empty). Is it possible to do this? Do I have to do it in redux-saga, i.e. if it is empty, give it up-to-date
// Update basic User's Data
exports.setUserdata = (req, res) => {
const id = req.params.userId;
User.update(
{
password: req.body.password,
name: req.body.name,
surname: req.body.surname,
email: req.body.email,
},
{ where: { id } },
)
.then(() => {
res.status(200).json({ success: true });
})
.catch(() => {
res.status(500).json({ error: 'Internal server error' });
});
};
Pass params you want to update and don't pass other keys.
If req.body contains only name key, you can just pick up those 4 keys from req.body.
const updateParams = _.pick(req.body, ['name', 'password', 'surname', 'email'])
User.update(updateParams, { where: { id } })
If req.body has other properties with value null or undefined, you can filter them after picking.
const updateParams = _.chain(req.body).pick(['name', 'password', 'surname', 'email']).filter().value()
User.update(updateParams, { where: { id } })
Of course it depends on the ORM you are using but I believe most ORM don't update attributes which are not passed at all.
I am using pg-promise.
I am having an issue trying to insert the following Javascript array:
[ { email: 'test1#gmail.com', password: 'test2' },
{ email: 'tes2t#gmx.com', password: 'test'3 },
{ email: 'test4#gmail.com', password: 'test4' },
{ email: 'test4#yahoo.com.ar', password: 'test5' }]
Using the following:
async function insertDB(data){
const cs = new pgp.helpers.ColumnSet(['email', 'password'], {table: 'users'});
console.log(data)
const query = pgp.helpers.insert(data, cs);
db.none(query)
.then(data => {
logger.info(" Query success: ", data);
})
.catch(error => {
logger.warn(" Query error: ", error);
});
}
and I get
UnhandledPromiseRejectionWarning: Error: Property 'password' doesn't exist.
**data.password = undefined**
**data[0] = { email: 'test1#gmail.com', password: 'test2' }**
How can I insert this data into my postgresdb?
// should create columnsets only once:
const cs = new pgp.helpers.ColumnSet(['email', 'password'], {table: 'users'});
function insertDB(data) {
// wrapping it into a function is safer, for error-reporting via query methods:
const query = ()=> pgp.helpers.insert(data, cs);
db.none(query)
.then(data => {
// data = null always here, no point displaying it
logger.info('Query success:', data);
})
.catch(error => {
logger.warn('Query error:', error);
});
}
And your function doesn't need async in this case.
UnhandledPromiseRejectionWarning: Error: Property 'password' doesn't exist.
You are confusing the JavaScript compiler, declaring the function as async, and then throwing an error synchronously while generating the insert, due to missing property password.
And if you want to insert some records without password, with null, for example, define your columnset like this:
const cs = new pgp.helpers.ColumnSet([
'email',
{name: 'password', def: null}
], {table: 'users'});
Other than that, type ColumnSet is ultimately flexible, see the documentation for each contained Column.
EXTRA
And if you want to use server-side DEFAULT value for missing passwords, you can provide it, with the help of Custom Type Formatting:
const DEFAULT = {rawType: true, toPostgres: ()=> 'DEFAULT'};
And then your password column can be defined like this:
{name: 'password', def: DEFAULT}
And there are many alternatives, with properties init and mod supported by Column.
I have some nested properties on my mogoose schema like this:
const userSchemaValues = {
username: {
type: String,
required: [true, 'Username required'],
trim: true,
unique: true,
lowercase: true
},
password: {
type: String,
required: [true, 'Password required'],
trim: true,
minlength: 8
},
...
prop: {
prop_1: String,
prop_2: String
}
};
valuesToUpdate.prop = _.pick(req.body, 'prop_1', 'prop_2');
log.debug(JSON.stringify(valuesToUpdate));
User.update({_id: req.params.id}, {$set: valuesToUpdate})
.then((data) => {
return res.json({message: data});
})
.catch(err => {
log.error(err);
return next({message: 'Error updating User.'});
});
But when I do User.update({_id: req.params.id}, {$set: valuesToUpdate}) on an User with prop_1 and _2 set with an object like this ({"prop":{"prop_1": "somevalue"}), it is not looking for what is in prop, it just overwrites it. How can I circumvent this?
Your find needs to include the property to update. Also the update statement needs the Positional Update Operator Change it to (outta my head):
valuesToUpdate.prop = _.pick(req.body, 'prop_1', 'prop_2');
log.debug(JSON.stringify(valuesToUpdate));
User.update({$and : [{_id: req.params.id}, {prop.prop1 : "%oldvalue%"}]}, {$set: { "prop.$.prop1" : "%newvalue""}})
.then((data) => {
return res.json({message: data});
})
.catch(err => {
log.error(err);
return next({message: 'Error updating User.'});
});
Note that the positional update only updates the FIRST occurrence!
UPDATE: After rereading your question i saw that the props is not an array... My bad sorry.
Luckily this makes it much easier :)
You do not require the field to be present in the find
for the set : { $set : { "prop.prop1" : "newvalue" }
Also the positional update is not required because it's not an Array.
This makes the following:
valuesToUpdate.prop = _.pick(req.body, 'prop_1', 'prop_2');
log.debug(JSON.stringify(valuesToUpdate));
User.update({_id: req.params.id}, {$set: { "prop.prop1" : "%newvalue%"}})
.then((data) => {
return res.json({message: data});
})
.catch(err => {
log.error(err);
return next({message: 'Error updating User.'});
});
UPDATE2: More information about the update statements.
Because of the comment's i'll clarify the update commands.
When you want to update a field in you document you use the $set command.
This updates one or more fields.
When you want to update multiple field you can do it with the command like:
$set : { "prop.prop1" : "newvalueforprop1", "prop.prop2" : "newvalueforprop2"} }
BUT when you use the command above and specify one one field it generates a command like:
$set : { "prop.prop1" : "newvalueforprop1", "prop.prop2" : null} }
This is all about how you create the update command. When you don't know if it's 1 or 2 properties you need to update your code so it generate a command dynamically.
But another thing you could do is let mongoose handle the update.
Use something like:
User.findById(req.params.id, function (err, user) {
if (err) {
handleError(err)
}
else {
//you should to some checking if the supplied value is present (!= undefined) and if it differs from the currently stored one
user.prop.prop1 = "your value";
user.prop.prop1 = "2nd value"
user.save(function (err) {
if (err) {
handleError(err)
}
else {
res.json(user);
}
});
}
});
Hope it's clear now.