I'm trying to save some data into a local mongodb database.
My schema looks as follows:
const mongoose = require('mongoose');
const userSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: String,
email: String,
passwordHash: String,
registerTimeStamp: { type: Number, default: Date.now() },
usersFollowing: [],
accountStatus: {
isBanned: { type: Boolean, default: false },
reason: { type: String, default: '' }
}
});
module.exports = mongoose.model('User', userSchema);
and the insert Method looks like this:
createUser(name, email, password) {
const passwordHash = "asdf";
const user = new User({
_id: new mongoose.Types.ObjectId(),
name,
email,
passwordHash
});
user.save(console.log("saved"));
}
my problem is, that even though I called the method with the right arguments, and it prints "saved", no data is inserted into the database.
Thanks!
First of all, when you call:
user.save(console.log("saved"));
The console will print "saved" no matter if you get or not an error. So maybe you are getting an error without a proper handler. If you really want to know what is happening with your user instance:
user.save()
.then(() => console.log("saved"))
.catch((error) => console.log(error));
If you want to use callbacks instead of promises:
user.save(function(error) {
if(error) throw error;
console.log("saved");
});
Now, there is an error in your insert method.
Change:
_id: new mongoose.Types.ObjectId(),
With:
_id: new mongoose.Types.ObjectId,
The parenthesis is the problem.
const mongoose = require('mongoose');
const userSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: String,
email: String,
passwordHash: String,
registerTimeStamp: { type: Number, default: Date.now() },
usersFollowing: [],
accountStatus: {
isBanned: { type: Boolean, default: false },
reason: { type: String, default: '' }
}
});
const User = mongoose.model('User', userSchema);
module.exports = User;
module.exports.createUser = function (name, email, password) {
const passwordHash = "asdf";
const user = new User({
_id: new mongoose.Types.ObjectId(),
name,
email,
passwordHash
});
User.save(user , callback);
}
The problem is that you are just logging the message, not saving the user in your database.
In order to do that, first you have to export the user model doing something like this:
const UserModel = mongoose.model('User', userSchema)
module.exports = UserModel
Next, in the same file where you have the createUser method, you import the UserModel. Then in your createUser method, you call the .save method but from your model just imported, sending the just created user:
const UserModel = require('../pathtothefile') //Here you specify the path of the user-model file
createUser(name, email, password) {
const passwordHash = "asdf"
const user = new User({
_id: new mongoose.Types.ObjectId(),
name,
email,
passwordHash
})
return UserModel.save(user)
}
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 have a user schema that looks like this:
const userSchema = new Schema({
email: {
type: String,
required: true,
unique: true,
trim: true
},
password: {
type: String,
required: true
},
role: {
type: String,
default: 'customer',
enum: ['customer', 'farmer', 'admin']
},
user_id: {
type: Schema.Types.ObjectId,
required: true,
unique: true
}
})
Additionally, I have another schema that would be called "customer" and looks something like this:
const customerSchema = new Schema({
company: String,
contact: String,
...etc
})
Now what I'd like to do is on creation of the User document, create and save a new Customer document, then save itd _id to my User document's user_id field.
The post request would look something like this:
// POST - USER REGISTRATION
router.post('/register', function (req, res) {
const { email, password, role } = req.body
const user = new User({ email, password, role,
user_id: new Customer({
company: req.body.company,
contact: req.body.contact,
...etc (rest of data)
})})
user.save(function(err) {
if (err) {
res.status(500)
.send("Failed to register. Please try again.")
}
else {
res.status(200).send("Registered.")
}
})
})
While this seems to create a Customer object (there's an ObjectID under user_id), the customer isn't saved to the database (naturally since .save isn't called).
My original approach here was to have a user_id variable set to null, then have customer create & save itself, then set the user_id variable to the customer._id value, but this didn't work as user.save(func(err)) would have a "null" user_id value.
just try like this
router.post("/register", async function (req, res) {
try {
const { email, password, role } = req.body;
let customer = new Customer({
company: req.body.company,
contact: req.body.contact,
});
let resultCustomer = await customer.save();
const user = new User({
email,
password,
role,
user_id: resultCustomer._id,
});
await user.save();
res.status(200).send("Registered.");
} catch (error) {
res.status(500).send("Failed to register. Please try again.");
}
});
I have this credit schema
const CreditSchema = new Schema({
userId: Schema.Types.ObjectId,
credit: {
type: Number,
default: 0
},
log: [String]
})
I hope it can be retrieve in below call
exports.getUser = async function(req, res) {
const user = await User.findOne({_id: req.query.id})
.populate('credit')
.exec()
res.json(user)
}
But what I get is userSchema's data, I don't see the data from credit schema. This is how my userSchema look like
const UserSchema = new Schema({
name: {
type: String
},
credit: {
type: Schema.Types.ObjectId,
ref: 'Credit'
}
})
I really scratch my head, I have the data in my db and the _id of userSchema is the same with userId of creditSchema.
This is the data of User and Credit
Maybe like this:
User.findOne({_id: req.query.id})
.populate("credit")
.exec(function (err: any, result: any) {
...//code
})
});
In my usersSchema I want to set a hashed password to my hash field. The schema looks like this:
// models/user-model.js
const usersSchema = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
unique: true,
required: true
},
hash: String,
salt: String
}, { timestamps: true });
usersSchema.methods.setPassword = (password) => {
this.salt = crypto.randomBytes(16).toString('hex');
this.hash = crypto.pbkdf2Sync(password, this.salt, 1000, 64).toString('hex');
};
In my route, I am trying to set a new user with a name, email, and password. Here's the route:
// routes/users.js
router.get('/setup', (req, res) => {
const user = new User();
user.name = 'Jacob';
user.email = 'jacob#gmail.com';
user.setPassword('password');
user.save()
.then((user) => {
const token = user.generateJwt();
res.json({ yourToken: token });
})
.catch((err) => {
res.json(err);
});
});
When I console.log(user) from the route, it gives me the following:
{ name: 'Jacob', email: 'jacob#gmail.com' }
I know that the setPassword method works as far as creating proper hashes. It does not, however, save those hashes to the user object. How do I apply setPassword to the user object that calls it so that it can set the salt and hash properties?
By using the fat arrow notation, you're changing what this is referring to in setPassword, so it's not pointing to the user document anymore.
Try using a regular function declaration:
usersSchema.methods.setPassword = function(password) {
this.salt = crypto.randomBytes(16).toString('hex');
this.hash = crypto.pbkdf2Sync(password, this.salt, 1000, 64).toString('hex');
};