# Mongoose Model Conventions
# Introduction
Mongoose (opens new window) is the most popular MongoDB object modeling tool. It provides a straight-forward, schema-based solution to model your application data. It includes built-in type casting, validation, query building, business logic hooks and more, out of the box.
To get started:
1.Install the mongoose package.
- Install mongoose unique validator
let’s create a Users model. Models typically live in the app directory.
# Establishing Mongoose connection
Interaction with the mongoose is possible once you setup a connection. To do that update your database details in .env file located in the root directory. Let assume we are working with MySql database.
DB_CONNECTION = mongoose; //database
DB_HOST = localhost; //database host
DB_PORT = 27017; //database port
DB_USER = database_user;
DB_PASSWORD = database_password;
DB_DATABASE = database;
You can also check database configuration file in 📘Config/database.ts. as it is reading the values in the .env file
import * as mongoose from "mongoose";
import { env, orm } from "expresswebcorets/lib/Env";
import { Path } from "expresswebcorets/lib/Utils/Path";
import { DBConnection, MongooseConfigurationType } from "expresswebcorets/lib/Database/DataSourceConfig";
export default {
/*
|--------------------------------------------------------------------------
| Database ORM
|--------------------------------------------------------------------------
| ExpressWeb currently supports the following Object Relational Mappers(ORM)
| Objection for sql databases and Mongoose for mongo DB. You need to select
| one depending on the type of database you are working on.
|
*/
ORM: env("ORM", orm.Mongoose),
/*
|--------------------------------------------------------------------------
| Database Provider
|--------------------------------------------------------------------------
| With respect to the orm you selected, you need to import the provider and
| assign it to provider.
| Example:
| for objection, import * as objection from "objection"
| for typeorm, import * as typeorm from "typeorm"
| Then assign typeorm to provider like this:
| provider: typeorm
|
*/
provider: mongoose,
/*
|--------------------------------------------------------------------------
| Database Multitenance
|--------------------------------------------------------------------------
| Database multitenance can be activated by switching the value to true and can
| be deactivated by switching it to false.
|
*/
database_multitenance: env("DB_MULTITENANCE", false),
/*
|--------------------------------------------------------------------------
| Multitenance Connections
|--------------------------------------------------------------------------
| Database multitenance connection enables interaction with multiple
| SQL databases where each database is a tenant in your system.
| The tenant array accepts an object of database connections (tenants).
|
*/
multitenant_tenants: DBConnection.multitenant<MongooseConfigurationType>("Mongoose", []),
/*
|--------------------------------------------------------------------------
| Database Connection
|--------------------------------------------------------------------------
| Here we define connection settings for both TypeORM, Objection, and mongoose.
| For typeORM, npm i --save typeorm
| For Objection, npm i --save objection
| For Mongoose, npm i --save mongoose
| --------------------------------------------------------------------------
| For SQL db, install the driver of your choice
| mysql driver, npm i --save mysql mysql2
| postgres driver, npm i --save pg pg-hstore
|
*/
connection: DBConnection.connect<MongooseConfigurationType>({
client: env("DB_DRIVER"),
connection: {
host: env("DB_HOST"),
port: env("DB_PORT"),
user: env("DB_USER"),
password: env("DB_PASSWORD"),
},
database: env("DB_DATABASE"),
}),
/*
|--------------------------------------------------------------------------
| Migration Configuration
|--------------------------------------------------------------------------
| Here we have database migration configuration.
| Which includes the following:
*/
migrations: {
directory: Path("Database/Migrations/"),
tableName: "migrations",
stub: Path("Database/Migrations/migrationLayout.stub"),
extension: "ts",
},
/*
|--------------------------------------------------------------------------
| Seed Configuration
|--------------------------------------------------------------------------
| Here we have database seed configuration.
| Which includes the following:
*/
seeds: {
directory: Path("Database/Seeds/"),
},
};
Once that is done, we can now create our model.
The easiest way to create a nosql model instance is using the make-nosql-model command:
Now, let’s look at an example User model, which we will use to retrieve and store information from our users database table:
import { mongoose, Schema, Document } from "Elucidate/Database/NoSQLModel";
import uniqueValidator from "mongoose-unique-validator";
export interface UserInterface extends Document {
first_name: string;
last_name: string;
email: string;
password: string;
}
const UserSchema: Schema = new Schema({
first_name: { type: String, required: true },
first_name: { type: String, required: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
});
UserSchema.set("timestamps", true);
UserSchema.plugin(uniqueValidator);
const User = mongoose.model<UserInterface>("User", UserSchema);
export default User;
# Model and Repository
To get started, let’s create a Users model. Models typically live in the App directory.
The easiest way to create a model instance is using the make-nosql-model command. If you would like to generate a database migration when you generate the model, use the m option:
Now, let’s look at an example User model, which we will use to retrieve and store information from our users database table:
import { mongoose, Schema, Document } from "Elucidate/Database/NoSQLModel";
import uniqueValidator from "mongoose-unique-validator";
export interface UserInterface extends Document {
first_name: string;
last_name: string;
email: string;
password: string;
}
const UserSchema: Schema = new Schema({
first_name: { type: String, required: true },
first_name: { type: String, required: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
});
UserSchema.set("timestamps", true);
UserSchema.plugin(uniqueValidator);
const User = mongoose.model<UserInterface>("User", UserSchema);
export default User;
Lets create our UserRepository class in 📘App/Repository directory.
import User, { UserInterface } from "App/Model/User_model";
import { MongooseRepository } from "Elucidate/Repository/Mongoose";
export class UserRepository extends MongooseRepository<UserInterface> {
constructor() {
super(User);
}
}
We can add other methods in our repository
import User from "App/Model/User_model";
import { MongooseRepository } from "Elucidate/Repository/Mongoose";
export class UserRepository extends MongooseRepository<UserInterface> {
constructor() {
super(User);
}
async findByName(first_name: string, last_name: string) {
return await this.findOne({ first_name, last_name });
}
}
Now we can use it in our UserService class in 📘App/Service/UserService directory.
import { UserRepository } from "App/Repository/UserRepository";
export class UserService {
public async getUser(first_name: string, last_name: string): Promise<User> {
return await new UserRepository().findByName(first_name, last_name);
}
}
We can also register UserRepository in AppServiceProvider and inject it in UserService
import { UserRepository } from "App/Repository/UserRepository";
import { UserService } from "App/Service/UserService";
import ServiceProvider from "Elucidate/Support/ServiceProvider";
export class AppServiceProvider extends ServiceProvider {
/**
* Register application services.
* @return void
*/
register(): Promise<void> {
this.singleton(UserRepository);
this.singleton(UserService);
}
}
We can now inject UserRepository into UserService
import { UserRepository } from "App/Repository/UserRepository";
export class UserService {
constructor(private userRepository: UserRepository) {}
public async getUser(first_name: string, last_name: string): Promise<User> {
return await this.userRepository().findByName(first_name, last_name);
}
}