I'm working at this project and I have users which have positive ranking. But I want to store others users id in an array which hit that "positive ranking button". I'm working with Mongoose and NodeJs.
I created the User Schema which contains the array and I searched for that user in my database, I get the user, but I'm stuck here, I don't know if I have to use a "for" to reach all array values or how do I check if the user has already "positive ranked" him.
This is my postPositiveRank function
exports.postPositiveRank = (req,res,next) =>{
const targetUser = req.body.targetUserId;
const loggedInUser = req.session.user._id;
User.findOne({"_id": targetUser}, function(err, process) {
for( let i = 0; i< process.positiveRanked.length;i++)
{
if(loggedInUser.equals(process.positiveRanked[i]))
{
//
}
else {
process.positiveRanked.push(loggedInUser);
process.positiveRanked.save();
}
}
})
}
And my User Schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const userSchema = new Schema({
firstname: {
type: String,
required: true
},
lastname: {
type: String,
required:true
},
age: {
type: Number,
required:true
},
occupation: {
type: String,
required:true
},
city: {
type: String,
required: true
},
county: {
type: String,
required:true
},
country: {
type:String,
required: true,
},
email: {
type: String,
required:true
},
password: {
type: String,
required:true
},
imageUrl: {
type: String,
required:true
},
rate:{
type:Number,
required:true
},
positiveRanked: [],
negativeRanked: []
});
module.exports = mongoose.model('User', userSchema);
I want that loggedInUser to be searched on the array even if it's positiveRanking or negativeRanking and if it is found to get back on the page with a message (I handle that ), and if it's not found to be added to the array.
I appreciate if you can help me, I hope I explained well.
There is a typo in your schema for positiveRanked please change that. You can use findIndex method on arrays to getIndex of the user you want to search if found it will return the index of the user in that array if not it will return -1 by this way you can avoid using for loop. I suggest using async/await because this is the better approach where you can keep your code clean and robust. If it did not work please let me know
exports.postPositiveRank = (req,res,next) =>{
const targetUser = req.body.targetUserId;
const loggedInUser = req.session.user._id;
User.findOne({"_id": targetUser}, function(err, process) {
const index=process.postitiveRanked.findIndex(id=>id===loggedInUser)
if(index!==-1)
{
// user found
}
else{
process.positiveRanked.push(loggedInUser);
process.save()
}
})
}
Using Async/await
exports.postPositiveRank = async (req,res,next) =>{
const targetUser = req.body.targetUserId;
const loggedInUser = req.session.user._id;
try{
let user = await User.findOne({"_id": targetUser})
const index=user.postitiveRanked.findIndex(id=>id===loggedInUser)
if(index!==-1)
{
// user found
}
else{
user.positiveRanked.push(loggedInUser);
await user.save()
}
}
catch(error){
console.log(error)
}
}
Related
I'm using NodeJS with Mongoose. I've two tables into db.js:
const mongoose = require('mongoose')
const UserSchema = new mongoose.Schema(
{
username: { type: String, required: true, unique: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true }
},
{ collection: 'users' }
)
const model = mongoose.model('UserSchema', UserSchema)
const AccountSchema = new mongoose.Schema(
{
username: { type: mongoose.Schema.Types.ObjectId, required: true, ref: 'hahaha' },
balance: { type: Number, required: true }
},
{ collection: 'accounts' }
)
module.exports.UserSchema = model
module.exports.AccountSchema = model
As you can see the first collection contains users (username, email, password). The second collection represents a bank account, related to a specific user. So, it has two fields: user (foreign key) and balance ($100, i.e.). First question: is my code correct to accomplish this task?
Second question: how can I insert data into the AccountSchema?
I obviously want to insert data only if the user exists into Userschema. I think that this doesn't work:
const Schema = require('./model/db')
app.post('/api/addaccount', async (req, res) => {
const { username, balance } = req.body
try {
const response = await Schema.AccountSchema.create({
username,
balance
})
console.log('User account successfully: ', response)
res.json({status : "ok"})
} catch (error) {
throw error
}
})
How can I do this?
This won't work. You've to query the User model first to check if any user exists with this username. If yes, you'll continue to store data in the Account model, if not you'll return a response something like user doesn't exist
Username doesn't get updated after running this. I also tried UpdateOne and it didn't work as well. The code was supposed to update an array but I tried updating the username to make it easier to track down the problem.
const mongoose = require('mongoose');
const schema = mongoose.Schema;
const userSchema = new schema({
Username:{
type: String,
required: true
},
Password:{
type: String,
required: true
},
Cart: Array
});
const User = mongoose.model('User', userSchema);
module.exports = User;
.
app.post('/putbox', (req, res) => {
var query = { Username: user };
var newvalues = { $push: { Cart: "Boxing" } };
try{
User.find(query).then((d)=>{
var values = d[0].Cart;
values.push("boxing")
User.findByIdAndUpdate(d._id, {Username: "test1"})
});
} catch(err) {
console.log(err);
}
res.redirect('/boxing');
});
I believe the syntax is not correct. The first element of updateOne searches for matches to update. You are just passing d._id which is not the same as the _id key in your db structure. Try this one
User.updateOne({ _id: d._id }, {Username: "test1"})
I am currently developing a platform in order to hone and develop my skills and am trying to encrypt the password for the necessary user signup. I want to do this via a virtual field. My problem is that I can not access the self-coded encryptPassword method even if I turn it into a regular function.
This is my code for my userSchema
const mongoose = require('mongoose');
const uuidv1 = require('uuidv1');
// uuidv1(); // ⇨ '1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed'
const crypto = require('crypto');
const userSchema = new mongoose.Schema({
name: {
type:String,
trim: true,
required:true
},
email: {
type:String,
trim: true,
required:true
},
hashed_password: {
type:String,
required:true
},
salt: String,
created : {
type: Date,
default: Date.now
},
updated: Date
});
//virtual field
userSchema.virtual('password')
.set((password) => {
// create temporarily varibale called _password
this._password = password;
//generate a timestamp
this.salt = uuidv1()
//encryptPassword()
this.hashed_password = this.encryptPassword(password);
})
.get(function() {
return this._password
});
//Methods
userSchema.method = {
encryptPassword: function(password){
if(!password) return "";
try {
return crypto.createHmac('sha1', this.salt).update(password).digest('hex');
} catch(err) {
return ""
}
}
};
module.exports = mongoose.model("User", userSchema);
The function in question is the encryptPassword function. I want to set the hashed_password with the encryptPassword function.
Thanks in advance for the help
I think you are missing one piece here, missing the function name. You can add methods to the schema like this:
// create methods with name
userSchema.methods.encryptPassword = function(password){
if(!password) return "";
try {
return crypto.createHmac('sha1', this.salt).update(password).digest('hex');
} catch(err) {
return ""
}
}
For more details, you can check the mongoose documentation for creating the instance methods.
The Problem was the way I structured that method. While using the mongoose way of structuring methods it worked.
userSchema.method({
authenticate: function(plainText){
return this.encryptPassword(plainText) === this.hashed_password
},
encryptPassword: function(password){
if(!password) return "";
try {
return crypto.createHmac('sha1', this.salt).update(password).digest('hex');
} catch(err) {
return ""
}
}
});
so I have two different collections for my social media app. One for the users and the other one for the user's posts. Whenever I'm updating the info from one of my user's collection it should also modify it on the post (since my post collection includes data from the user too), but it's only doing it on the posts that I create after that and not on the ones that I've been creating before. How can I fix it?
USER SCHEMA
const userSchema = new Schema({
name: { type: String, required: true },
lastname: { type: String, required: true },
username: { type: String, required: true },
email: { type: String, required: true },
password: { type: String, required: true, minlength: 8 },
avatar: { data: Buffer, contentType: String },
});
POST SCHEMA
const postSchema = new Schema({
user: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
name: { type: String, required: true },
lastname: { type: String },
username: { type: String },
avatar: { data: Buffer, contentType: String },
date: { type: Date, default: Date.now() },
textOfThePost: { type: String, required: true },
});
EDIT FUNCTION EXPRESS/MONGOOSE
router.put("/edit_profile", async (req, res) => {
try {
const { name, lastname, username } = req.body;
const user = await User.findById(req.user).select("-password");
if (!user) return res.status(404).json("User doesn't exists");
if (name) user.name = name;
if (lastname) user.lastname = lastname;
if (username) user.username = username;
await user.save();
res.json(user);
} catch (err) {
res.status(500).json({ error: err.message });
}
};
You can use updateMany() for that purpose.
const res = await Post.updateMany({ user: user.id }, { name: user.name, username: user.username /* ... */ });
However as already pointed out you are storing user data redundant on the post model as well as on the user model which is not necessary. Similar to joins in SQL you can simply use populate() and not store any user-related data on your post model. This way everytime you query your posts it will automatically pull the latest matching user model by its id.
myPost.populate('user')
Note that therefore the ref is required, which tells mongoose how to populate the user field.
I have Course Schema like below
const studentSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
current_education: {
type: String,
required: true
},
course_name: {
type: mongoose.Schema.Types.ObjectId,
ref:'Course'
},
address: {
type: String,
required: true
},
mobile_number: {
type: Number,
required: true
},
date: {
type: Date,
default: Date.now
}
})
and I'm trying to make relationship student to the course. In the controller, I'm trying to populate the course details based on the course ID like below
exports.createStudent = async (req, res) => {
try {
const student = new Student(req.body);
const result = await student.save().then(t => Course.findById(req.body.course_name).populate('courses'));
if (!result) res.send('something went wrong');
res.send(result)
} catch (e) {
res.send(e);
}
}
In the postman how I'm posting you can check it below
{
"name":"Ram",
"current_education":"B.tech",
"course_name":"5cb804f1e97ba91cb8ca9dac",
"address":"Bangalore",
"mobile_number":7894561236
}
Important: Here courseID is existed in the database
the data is saved successfully in the database but the course details not populated except id. the resultant data in the database look like below
I guess you want Student details along with the course details:
Here's how you achieve it:
exports.createStudent = async (req, res) => {
try {
const student = new Student(req.body);
const result = await student.save().then(t =>
Student.findById(student._id).populate('course_name')); // Pass new ID and then populate the "course_name"
if (!result) res.send('something went wrong');
res.send(result)
} catch (e) {
res.send(e);
}
}
Hope this solves your query!