# 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;
Copied!
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/"), }, };
Copied!
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;
Copied!
# 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;
Copied!
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); } }
Copied!
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 }); } }
Copied!
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); } }
Copied!
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); } }
Copied!
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); } }
Copied!