Creating Seeds for MongoDB with Faker and Bcrypt

Alexander Khoroshilov
5 min readMar 25, 2023

Introduction

In this article, we will explore how to create seeds for MongoDB using the popular libraries Faker and Bcrypt. We will focus on creating user records with hashed passwords for a hypothetical application. To achieve this, we will go through a code example line by line, explaining the process and the purpose of each line.

Before diving into the code, make sure you have the following dependencies installed:

  1. mongoose
  2. faker
  3. bcrypt

You can install all of it just by using npm or yarn:

npm install mongoose faker bcrypt

Firts of all, we need to create our User model for Mongo.

  1. Import the required libraries:
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');

2. Define the User schema:

const UserSchema = new mongoose.Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
address: {
street: {
type: String,
required: true,
},
city: {
type: String,
required: true,
},
state: {
type: String,
required: true,
},
zip: {
type: String,
required: true,
},
},
phone: {
type: String,
required: true,
},
registeredAt: {
type: Date,
default: Date.now,
},
});

Here, we define the User schema using mongoose.Schema. We set up fields like name, email, password, address, phone, and registeredAt, specifying their data types, and whether they are required or unique.

3. Hashing:

UserSchema.pre('save', async function (next) {
if (this.isModified('password') || this.isNew) {
try {
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(this.password, salt);
this.password = hashedPassword;
next();
} catch (error) {
next(error);
}
} else {
next();
}
});

In this block, we define a pre-save hook on the UserSchema using the pre method. This function will be executed before a document is saved to the database. The hook checks if the password field has been modified or if the document is new. If so, it generates a salt using bcrypt.genSalt(10) and hashes the user's password with the salt using bcrypt.hash(this.password, salt). Then, it sets the hashed password to the password field of the document. If there's an error during the process, it passes the error to the next middleware. If the password has not been modified or the document isn't new, it simply proceeds to the next middleware.

4. Finally, Export the User model:

module.exports = mongoose.model('User', UserSchema);

Finally, we create a Mongoose model named ‘User’ using the defined UserSchema and export it, so it can be used in other parts of the application.

Full Listing of our User model:

const mongoose = require('mongoose');
const bcrypt = require('bcrypt');

const UserSchema = new mongoose.Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
address: {
street: {
type: String,
required: true,
},
city: {
type: String,
required: true,
},
state: {
type: String,
required: true,
},
zip: {
type: String,
required: true,
},
},
phone: {
type: String,
required: true,
},
registeredAt: {
type: Date,
default: Date.now,
},
});

UserSchema.pre('save', async function (next) {
if (this.isModified('password') || this.isNew) {
try {
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(this.password, salt);
this.password = hashedPassword;
next();
} catch (error) {
next(error);
}
} else {
next();
}
});

module.exports = mongoose.model('User', UserSchema);

Seeeeeeeed

Now, it’s finally time to talk about our seed. Create a new file AddUsers.js and lets begin.

  1. Import required libraries and our User model:
const mongoose = require('mongoose');
const User = require('../models/user');
const faker = require('faker');
const bcrypt = require('bcrypt');

We import mongoose for MongoDB operations, the User model (which should have been defined as in the previous answer), faker for generating fake data, and bcrypt for hashing passwords.

2. Define the database connection URL (I am using local machine):

const localUrl = 'mongodb://localhost:27017/test';

We define the MongoDB connection URL for a local instance, pointing to the test database.

3. Connect to the database:

mongoose
.connect(localUrl, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => {
console.log('Connected correctly to DB server');
})
.catch((err) => {
console.log(err.stack);
});

We connect to the MongoDB instance using mongoose.connect, passing the connection URL and options to enable useNewUrlParser and useUnifiedTopology. We also handle the success and error cases using then and catch, respectively.

4. Define the createUsers function:

async function createUsers() {
try {
const userCount = faker.datatype.number({
min: 20,
max: 30,
});

for (let i = 0; i < userCount; i++) {
const plainPassword = faker.internet.password();
const hashedPassword = await bcrypt.hash(plainPassword, 10);
const newUser = new User({
name: `${faker.name.firstName()} ${faker.name.lastName()}`,
email: faker.internet.email(),
password: hashedPassword,
address: {
street: faker.address.streetAddress(),
city: faker.address.city(),
state: faker.address.stateAbbr(),
zip: faker.address.zipCode(),
},
phone: faker.phone.phoneNumber(),
});
const savedUser = await newUser.save();
console.log('User created:', savedUser);
}
} catch (error) {
console.error('Error while creating users:', error);
} finally {
mongoose.connection.close();
}
}

In this block, we define an asynchronous createUsers function. It begins by generating a random number of users to create using faker.datatype.number. Inside the loop, we create a plain-text password using faker.internet.password() and then hash the password using bcrypt.hash(). We create a new User instance with fake data provided by Faker and the hashed password. The user instance is then saved to the database, and the created user is logged to the console. If any errors occur during this process, they are caught and logged. Once all users have been created, the database connection is closed.

5. Last thing: Call the `createUsers` function:

createUsers();

Finally, we invoke the createUsers function, which runs the entire process of generating and saving users to the MongoDB database.

Now, let’s break down the Full listing of the Seed code:

const mongoose = require('mongoose');
const User = require('../models/user');
const faker = require('faker');
const bcrypt = require('bcrypt');

const localUrl = 'mongodb://localhost:27017/delivery';

mongoose
.connect(localUrl, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => {
console.log('Connected correctly to DB server');
})
.catch((err) => {
console.log(err.stack);
});

async function createUsers() {
try {
const userCount = faker.datatype.number({
min: 20,
max: 50
});

for (let i = 0; i < userCount; i++) {
const plainPassword = faker.internet.password();
const hashedPassword = await bcrypt.hash(plainPassword, 10);

const newUser = new User({
name: `${faker.name.firstName()} ${faker.name.lastName()}`,
email: faker.internet.email(),
password: hashedPassword,
address: {
street: faker.address.streetAddress(),
city: faker.address.city(),
state: faker.address.stateAbbr(),
zip: faker.address.zipCode(),
},
phone: faker.phone.phoneNumber(),
});
const savedUser = await newUser.save();
console.log('User created:', savedUser);
}
} catch (error) {
console.error('Error while creating users:', error);
} finally {
mongoose.connection.close();
}
}

createUsers();

Conclusion

In this article, we learned how to create seeds for MongoDB using Faker and Bcrypt. I demonstrated the process of creating user records with hashed passwords by breaking down a code example line by line. This method can be extended to generate seeds for any kind of data, making it a versatile approach for populating your database for development and testing purposes.

You can now apply this knowledge to your own projects, ensuring your applications have realistic and secure data for development and testing. Happy coding!

--

--

Alexander Khoroshilov

Accomplished and innovative Front-end Web Developer with 10 years of experience and extensive experience in web development and full-stack projects.