Mongo Model
Overview
We are following the ODM
object data modeling pattern, which dictate that for each document in the mongo db, we'll
have a Model
in our codebase which will contain the definition regarding how our database document will look like, what fields it'll have and how to
validate them like unique
, required
validations. We are using Mongoose to define these models
and to communicate with the MongoDB.
Mongoose
In order to communicate with the database we are using Mongoose. An object data modeling ( ODM) library specifically designed for NodeJS to work with the MongoDB. What this means in practical terms is that you can define your data model in just one place, in your code. It allows defining schemas for our data to fit into, while also abstracting the access to MongoDB. This way we can ensure all saved documents share a structure and contain required properties.
Schema
While Mongo is schema-less, SQL defines a schema via the table definition. A Mongoose Schema is a document data structure (or shape of the document) that is enforced via the application layer.
Models
Models are fancy constructors compiled from Schema definitions. An instance of a model is called a document. Models are responsible for creating and reading documents from the underlying MongoDB database.
Defining Model
import { Connection, Document, Model, Schema } from 'mongoose';
import { addIdVirtualFields, commonModeSchemaOptions } from '@common-stack/store-mongo'; // Common Utility funtion, for common opeations
import { IUser } from 'generated-modals'; // Typescript definiton for the Model
export type IUserMongoModel = Document & IUser;
export type UserModelType = Model<IUserMongoModel>;
// First Step is to Define Schmea
export const userScehma = new Schema<IUserMongoModel>(
{
firstName: { type: Schema.Types.String },
lastName: { type: Schema.Types.String },
email: { type: Schema.Types.String, required: true, unique: true },
active: {type: Schema.Types.Boolean, default: false},
// For collection you just need to pass the field definiton inside brackets []
comments: [{ type: Schema.Types.ObjectId, ref: 'commments' }] // Just to explain, how we can have cross document ref
},
commonModeSchemaOptions, // Adds timestamos (createdAt, updatedAt)
);
// Once schema is defined we can add/override methods on the schmea object
addIdVirtualFields(userScehma); // Add `id` field which will contain document objectId, instead of `_id`
// By calling `.model` on active db connection we instantiate a `model` instance (document).
// Firs param is the name of the `collection`, which should always be plural whereas the second one is the schema definition of that model
export const UserModelFunc: (db: Connection) => UserModelType = (db) =>
db.model<IUserMongoModel>('users', userScehma);
The next step is to Define Repository for this model.