I want to make a function that create a new task for a specific user - node.js

I have 2 models in relation a User model and a Task model each user have inside an empty task array and I want a function that get the user by email and push a new task to the users task array I tried a lot but I don't made that function to work so I need some help here is my code.
User model:
const { Schema } = mongoose;
//connecting mongoose to mongoDB
mongoose.connect("mongodb+srv://tudor:tudor#cluster0.gbojb.mongodb.net/<dbname>?retryWrites=true&w=majority", { useNewUrlParser: true, useUnifiedTopology: true, useFindAndModify: false });
const { Post } = require("./PostModel")
const userSchema = new Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
minlength: [5, 'The password should have more then 5 characters']
},
age: {
type: Number,
required: true,
},
description: {
type: String,
required: true,
maxlength: [300, 'Description should have less then 300 characters']
},
tasks: [{
type: Schema.Types.ObjectId,
ref: "task"
}]
})
const User = mongoose.model('User', userSchema);
exports.User = User
task model
const mongoose = require("mongoose")
const Schema = mongoose.Schema
let TaskSchema = new Schema({
content: String,
owner: {
type: Schema.Types.ObjectId,
ref: "User"
}
})
module.exports = mongoose.model("Task", TaskSchema)
And here I want to make the function :
const createNewTask = async (req, res, next) => {
const userEmail = req.params.id;
}

This is how your function will work:
const createNewTask = async (req, res, next) => {
const userEmail = req.params.id;
// find user first by email
const userData = await User.findOne({email: userEmail});
// add check here if user exist or not (not writing it for now)
// now create task by extract task payload (assuming you have detail in body)
const taskData = await Task.create({
content: req.body.content,
owner: userData._id,
});
// now push task id in user
await User.updateOne({
email: userEmail
}, {
$push: {tasks: taskData._id},
});
}
There can be some errors since didn't tested it but you get the idea how to do it.

Related

Log a user in and get their profile

I am attempting to log a user in to my DB. When I log the user in, it returns the first userId in the DB and not the user who logged in. I have been struggling with this for a while and really am at a dead end.
This is my POST route to log the user in:
// login
router.post("/login", async (req, res) => {
const user = await User.findOne({
email: req.body.email,
});
const secret = process.env.SECRET;
if (!user) {
return res.status(400).send("the user not found!");
}
if (user && bcrypt.compareSync(req.body.password, user.passwordHash)) {
const token = jwt.sign(
{
userId: user.id,
isAdmin: user.isAdmin,
},
secret,
{ expiresIn: "1d" }
);
res.status(200).send({ user: user.email, token: token });
} else {
res.status(400).send("password is wrong!");
}
});
The const user = await User.findOne({ email: req.body.email, }); this returns the wrong user.
When I query the endpoint get a users profile with the userId it gets the right information. So its got nothing to do with the DB.
This is the call in the app.
const handleSubmit = () => {
axios
.post(`${baseURL}users/login`, {
email: email,
passwordHash: password,
})
.then(res => {
console.log('USER ID TOKEN', res.data.token);
setbearerToken(res.data.token);
AsyncStorage.setItem('bearerToken', res.data.token);
const decoded = decode(res.data.token);
setTokenID(decoded.userId);
dispatch(setUser(res.data));
});
};
user.js model
const userSchema = mongoose.Schema({
contactName: {
type: String,
required: true,
minlength: 5,
maxlength: 50
},
phone: {
type: String,
required: true,
minlength: 5,
maxlength: 50
},
passwordHash: {
type: String,
required: true,
minlength: 5,
maxlength: 1024
},
token: {
type: String,
},
isAdmin: {
type: Boolean,
default: false
},
clubName: {
type: String,
required: true,
},
clubAddress: {
type: String,
required: true,
},
clubEmail: {
type: String,
required: true,
},
clubPhone: {
type: String,
required: true,
},
clubWebsite: {
type: String,
required: true,
},
clubContact: {
type: String,
required: true,
},
})
Your schema doesn't have a field email to filter on.
const user = await User.findOne({
email: req.body.email,
});
Maybe you try clubEmail field. I reproduced the behavior and it looks like that mongoose ignores the filter if the field does not exist in the Schema an just returns the first document in the collection.
E.g.
const userSchema = new Schema(
{
name: String,
age: Number
}
)
const User = mongoose.model('User', userSchema);
User.findOne({name: "Superman"}, ...
Returns the user with name "Superman".
const userSchema = new Schema(
{
name: String,
age: Number
}
)
const User = mongoose.model('User', userSchema);
User.findOne({xname: "Superman"}, ...
But when using xname in the filter document which does not exist in my schema neither in the collection as field the query returns the first document in my test collection (its not Superman).
Also look here similar issue: Model.find Mongoose 6.012 always return all documents even though having filter
Issue reported: https://github.com/Automattic/mongoose/issues/10763
Migration Guide to Mongoose 6:
https://mongoosejs.com/docs/migrating_to_6.html#strictquery-is-removed-and-replaced-by-strict

joi with mongoose schema

I'm trying to use joi module on mongoose schema but it doesn't work
everything works except joi validation
the module was installed and required.
schema:
const mongoose = require("mongoose");
const joi = require("joi");
const userSchima = new mongoose.Schema({
name: {
type: String,
required: [true, "use must have a name"],
unique: true,
trim: true,
},
email: {
type: String,
required: [true, "use must have an email"],
unique: true,
trim: true,
},
password: {
type: String,
required: [true, "use must have an password"],
},
});
const User = mongoose.model("User", userSchima);
// const validateUser = (User) => {
// const schema = {
// name: joi.string().min(2).max(15),
// email: joi.types.String().email().required(),
// password: joi.minOfUppercase(1).minOfNumeric(2).noWhiteSpaces().required(),
// };
// return joi.validate(User, schema);
// };
// module.exports = validateUser;
module.exports = User;
create async fun from the controller:
i didn't add the catch method because of to much code here
exports.creatUser = async (req, res) => {
try {
const newUser = await User.create(req.body);
res.status(200).json({
status: "success",
data: {
user: newUser,
},
});
}
thanks from help

Implementing text search with Mongoose

I want to implement text search on my app, and find documents where the field login matches the searched term,
I did the code below and I have no errors but the result in the route is always an empty array, there must be an error somewhere
Model
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const UserSchema = new Schema({
created_at: {
type: String,
required: true,
},
description: {
type: String,
required: true,
},
display_name: {
type: String,
required: true,
index: true,
},
login: {
type: String,
required: true,
index: true,
},
});
UserSchema.index({ login: "text", display_name: "text" });
User = mongoose.model("users", UserSchema);
User.createIndexes();
module.exports = User;
Route
router.post("/users", async function (req, res) {
const { search } = req.body;
const users = await User.find({ $text: { $search: search } });
res.send(users);
});

MongoDB populate() to dynamically load/migrate data not working

I am building an app in which the user adds and deletes objects (Pic) in an array('pics') after registering, but not sure how to dynamically load or populate('pics') to userSchema to automatically render. The user registers on the app with that array originally empty ('pics' = zero), and will create or delete those objects thereafter when logged in.
Following the documentation, I used "await User.find().populate('pics');" to migrate data in index method, but did not work.
Besides, should I include 'pics' key at store method, or userSchema 'pics' should be enough?
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true,
trim: true
},
pics: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Pic"
}
],
});
const picSchema = new mongoose.Schema({
thumbnail: String,
description: String,
dev: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
},
);
const User = mongoose.model('User', userSchema);
const Pic = mongoose.model('Pic', picSchema)
async index(req, res, next) {
const users = await User.find().populate('pics');
res.status(200).json(
devs
);
},
async store(req, res) {
try {
const { name } = req.body;
let user = await User.create({
name,
pics
})
// await user.populate('pics').execPopulate();
res.send({ user })
}
} catch (error) {
res.status(400).send(error);
}
},
I worked a time ago with MongoDB and NodeJS. I think that you have a problem with the definitions. Also, you can read the documentation https://mongoosejs.com/docs/populate.html
You need to define the _id for collections (Schema).
const userSchema = new mongoose.Schema({
_id: new mongoose.Types.ObjectId(),
name: {
type: String,
required: true,
trim: true
},
pics: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Pic"
}
],
});
const picSchema = new mongoose.Schema({
_id: new mongoose.Types.ObjectId(),
thumbnail: String,
description: String,
dev: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
},
);
So, when you create a new User, the _id is completed (you can generate it or it can be generated automatically) and ignore the field pics. When you create a Pic, you need to read the _id of the User and assigned as 'dev', something like:
let pic = new Pic({
thumbnail: '', description: '',
dev: yourUser._id
});
Using this way to create documents, you can use the populate function.

Getting all Posts that belong to one User and display to pass to the view Node / Express / Mongoose

Below is the code for User model, Post model and the route. I need to query the DB and then pass to the view through the router. What am I missing?
User model:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var userSchema = new Schema({
firstName: {
type: String,
required: true
},
lastName: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
}
});
module.exports = mongoose.model('User', userSchema);
Posts model:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var postSchema = new Schema({
postTitle: {
type: String,
required: true
},
postStory: {
type: String
},
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
username: String
}
});
module.exports = mongoose.model('Post', postSchema);
And here is the query in the router that I'm trying but apparently it's not the way to go...
My GET route:
router.get('/dashboard', isLoggedIn, function(req, res) {
Post.find({author:req.user._id}, (err, posts) => {
if(err) {
console.log(err);
} else {
res.render('users/dashboard', {currentUser: req.user, posts: posts});
}
});
});
What am I missing here?
You may want to change the find query to match the proper attribute in the following line:
Post.find({author: req.user._id}, (err, posts) => {
to be:
Post.find({'author.id': req.user._id}, (err, posts) => {
Read more: http://mongoosejs.com/docs/2.7.x/docs/finding-documents.html

Resources