Mission 2: Be a Mongoose Master
Tags: mongodb, nosql, beginners, database
Published: 2023-11-13 20:11:46

# Module 5: In-Depth Exploration of MongoDB Queries

## 5-0 Introduction of be a Mongoose Master

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u3uv0vt4n4bbc4qgyn9b.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cn2vnfufzprt5x3a2gh7.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s2psy7pvk31ygddmv6ck.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7ofopooptbq7jfxh7ow0.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vizz8znnvmb6knkyh9cc.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q4qmn0horsairnj0i6uw.png)

## 5-1-A Install MongoDB compass & No SQL Booster ( windows)
## 5-1-B Install MongoDB compass & No SQL Booster ( Mac & Linux)
=> https://www.mongodb.com/try/download/community









# Module 6: Mastering MongoDB Aggregation & Indexing

## 6-0 Introduction of powerful aggregation framework

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pay86sixxx4f2bxf023w.png)

## 6-1 $match , $project aggregation stage

```js
db.test.aggregate( [

   // Stage 1: 
   {
      $match: { gender: "Male" , age: {$lt: 30}}
   },

  // Stage 2: 
  {
      $project: {name:1, age:1,gender:1} 
  }

] )
```

## 6-2 $addFields , $out , $merge aggregation stage
=> 
=> 

```js
//6-0 Introduction of powerful aggregation framework
db.test.aggregate( [

  // Stage 1: 
  {
      $match: { gender: "Male" , age: {$lt: 30}}
  },

  // Stage 2: 
  {
      $addFields: {course: "level-2"} //addfileds works temporary to add a new field
  },
  
  {
      $project: {course:1}
  },
//   {
//       $out: "course-students" //out use for create a new collection and use addfields temporaty data to merge in a new collection collection
//   },
  {
      $merge: "test" // merge my new field in the test collection
  }

] )
```

## 6-3 $group , $sum , $push aggregation stage

```js
//group
db.test.aggregate( [
    //stage-1
    {$group:{_id:"$gender"}}
] )
```

```js
//count sum
db.test.aggregate([
    //stage-1
    { $group: { _id: "$address.country", count: {$sum: 1 }} }
])

```

```
//use push
db.test.aggregate([
    //stage-1
    { $group: { _id: "$address.country", count: {$sum: 1 }, showMeName:{$push:"$name"}} }
])
```

```
//use $$ROOT
db.test.aggregate([
    //stage-1
    {
        $group: {
            _id: "$address.country",
            count: { $sum: 1 },
            fullDoc: { $push: "$$ROOT" }
        }
    },
    //stage-2==> want to send only name email and phone
    {
        $project: {
            "fullDoc.name":1,
            "fullDoc.email":1,
            "fullDoc.phone":1,
        }
    }
])
```


## 6-4 explore more about $group & $project

```js
//total salary
db.test.aggregate([
    //stage-1
    {
        $group: {
            _id: null,
            totalSalary : {$sum: "$salary"}
        }
    },
])

```

```js
db.test.aggregate([
    //stage-1
    {
        $group: {
            _id: null,
            totalSalary: { $sum: "$salary" }, // total salary
            maxSalary: { $max: "$salary" }, // maximum salary
            minSalary: { $min: "$salary" }, // minium salary
            avgSalary: { $avg: "$salary" } // average salary
        }
    },
    //stage-2
    {
        $project: {
            totalSalary: 1,
            maxSalary: 1,
            minSalary: 1,
            avgSalary: 1,
            averageSalary: "$avgSalary",  // or we can also write 
            rangeMaxMinusMin:{$subtract:["$maxSalary","$minSalary"]} //max salary minus min salary
        }
    }
])
```

## 6-5 Explore $group with $unwind aggregation stage

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jl089hdkq3jgpb3dfyaq.png)

```js
db.test.aggregate([
    //stage-1
    {
        $unwind: "$interests"
    },
    //stage-2
    {
        $group: { _id: "$age", interestperage:{$push:"$interests"}}
    }
])
```

## 6-6 $bucket, $sort, and $limit aggregation stage

```js
db.test.aggregate([
    //stage-1
    {
        $bucket: {
            groupBy: "$age",
            boundaries: [20, 40, 60, 80],
            default: "80 er upor bura gula",
            output: {
                count: { $sum: 1 },
                sobarname: { $push: "$name" }, // sobar name nisi
                allDocuments: { $push: "$$ROOT" } // ARRAY of objects a all documets nia nisi
            }
        }
    },
    //stage-2
    {
        $sort: {count:-1}
    },
    //stage-3 => if i want i can output only 2 documents
    {
        $limit: 2
    },
    //stage-4
    {
        $project: {count:1}
    }
])
```

## 6-7 $facet, multiple pipeline aggregation stage

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xog20mabyiyznsrwmm26.png)

```js

db.test.aggregate([
    {
        $facet: {
            //pipeline-1
            "friendscount": [
                {
                    $unwind: "$friends"
                },
                {
                    $group: { _id: "$friends", count: { $sum: 1 } }
                }
            ],
            //pipeline-2
            "educationCount": [
                {
                    $unwind: "$education"
                },
                {
                    $group: { _id: "$education", count: { $sum: 1 } }
                }

            ],
            //pipeline-3
            "skilslcouunt": [
                {
                    $unwind: "$skills"
                },
                {
                    $group: { _id: "skills", count: { $sum: 1 } }
                }

            ]
        }
    }

])
```

## 6-8 $lookup stage, embedding vs referencing

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7ieyoi5vmys2wbn0qaj1.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ynmf62muhmkq6yegvpc9.png)


```js
db.orders.aggregate( [
   {
     $lookup:
       {
         from: "test",
         localField: "userId",
         foreignField: "_id",
         as: "user"
       }
  }
] )
```

## 6-9 What is indexing, COLLSCAN vs IXSCAN

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gm187ctfqe2bjfymsisq.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d3lcjvhvvh2yapqyfo19.png)



## 6-10 Explore compound index and text index

```js
db.getCollection("massive-data").createIndex({ age: 1 })

```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r2a4jthlxvvk0aajlc8k.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/btxdma16svfke8lhilix.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/76vq5ovbwywmp2mzjhj5.png)


# Module 7:Mastering The Foundation Of Express

## 7-1 What is nodejs , a high level overview of node.js

## 7-2 What is module, commonjs vs esm

```js
=>local1.js
const add = (parm1, parm2)=> parm1+parm2
const a=10

module.exports={
    add,
    a
}

// console.log(module)

//built-in-modules-1
const path = require("path")
console.log(path.dirname("/home/rakib/Desktop/1.NextLevelWebDevelopment/ts/module1/dist/inde.js"))

//built-in-modules-2
const path = require("path")
console.log(path.parse("/home/rakib/Desktop/1.NextLevelWebDevelopment/ts/module1/dist/inde.js"))

=>local2.js
const add = (parm1, parm2,parm3)=> parm3+parm1+parm2
const a=10

module.exports={
    add,
    a
}
module.exports=add
=>index.js
const {add,a} = require('./local1')
const {add:add2,a:a2} = require('./local2')
console.log(a)

```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rcx50qvxu70zep5a7vzs.png)

```js
const fs = require('fs')

//reading a file text
const readText= fs.readFileSync('./texts/read.txt', 'utf-8')

console.log(readText)

//writting a text
const writternText = fs.writeFileSync('./texts/write.txt', readText + 'Thsi is rakib')
console.log(writternText);
```

## 7-3 File System Module , synchronous vs asynchronous

```js
const fs = require('fs')

//reading text asynchronously

fs.readFile('./texts/read.txt', 'utf8', (err, data) => {
    if (err) {
        throw Error('error reading')
    }
    // console.log(data);

    // write text file asynchornosuly
    fs.writeFile('./texts/read2.txt',data, 'utf8', (err) => {
        if (err) {
            throw Error('error writing')
        }
        console.log('The file has been saved!');
    });
});


```

## 7-4 Event driven architecture, create your own events

```js
const EventEmitter = require('events');
const myEmitter = new EventEmitter();

// First listener
myEmitter.on('event', () =>{
  console.log('Helloooo! first listener');
});
// Second listener
myEmitter.on('event', (arg1, arg2) => {
  console.log(`event with parameters ${arg1}, ${arg2} in second listener`);
});
// Third listener
myEmitter.on('event', (...args) =>{
  const parameters = args.join(', ');
  console.log(`event with parameters ${parameters} in third listener`);
});

// console.log(myEmitter.listeners('event'));

myEmitter.emit('event', 1, 2, 3, 4, 5);
```

## 7-5 Stream and buffer, create your own server

```js
const http = require('http');

// Create a local server to receive data from
const server = http.createServer();

// Listen to the request event
server.on('request', (request, res) => {
  //   res.writeHead(200, { 'Content-Type': 'application/json' });
  console.log(request)

  res.end(JSON.stringify({
    data: 'Hello World!',
  }));
});

server.listen(5000, () => {
  console.log(`server is listening on port 5000 {$port}`)
});

//===> to run node filename.js

```

## 7-5 Stream and buffer, create your own server

```js
const http = require('http');
const fs = require('fs');

// Create a local server to receive data from
const server = http.createServer();

// Listen to the request event
server.on('request', (request, res) => {

  if (request.url === '/read-file' && request.method === 'GET');

//straming file reading
    const readblestram = fs.createReadStream(process.cwd() + '/texts/read.txt');

    readblestram.on('data', (buffer) => {
      res.statusCode = 200;
      res.write(buffer);
    });

    readblestram.on('end', () => {
      res.statusCode = 200;
      res.end('HAPPY ENDING');
    });

    readblestram.on('error', (error) => {
      console.log(error);
      res.statusCode=500;
      res.end('something went wrong');
    });

});

server.listen(5000, () => {
  console.log(`server is listening on port 5000 {$port}`)
});
```

## 7-6 Installing express, typescript

```js
npm init
yarn add express
yarn add -D typescript
tsc --init
yarn add -D @types/node
yarn add -D @types/express
yarn add -D nodemon
```

```
"rootDir": "./src/",
"outDir": "./dist/",     
```
```
tsc -w
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/97mcqplmfoxm5y0t3sug.png)
```
"start-dev" : "nodemon ./dist/app/server.js",
rakib@pop-os:~/Documents/project-1/dist/app$ yarn start-dev    
```




```ts
//app.ts
// const express = require('express')
import express from 'express';
const app = express();
const port = 3000;

app.get('/', (req, res) => {
    res.send('Hello World!')
})

export default app;
```

```ts
//server.ts
import { Server } from 'http';
import app from './app';

const PORT = 5000;

let server: Server;


async function bootstrap() {
    server = app.listen(PORT, () => {
        console.log(`Example app listening on port ${PORT}`)
    });
}

bootstrap();
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zgimqclrzdf84fzudnno.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ruxt45hm7qoaeznsduwe.png)

## 7-7 What is parsers, request and response object
`tsc`

```js
import express, {Request, Response} from 'express';

app.get('/', (req: Request, res:Response) => {
```

```
yarn add -D nodemon
"start-dev": "nodemon ./dist/app/server.js",
```

```js
//perser
app.use(express.json());
app.use(express.text());
```

```js
app.post('/', (req: Request, res:Response) => {
    console.log(req.body);
    res.json({
        message: "suffesfully done"
    })
})

```

## 7-8 middleware in express.js

```js
// const express = require('express')
import express, {Request, Response, NextFunction } from 'express';

const app = express();
const port = 3000;

//perser
app.use(express.json());
app.use(express.text());



// Your custom "middleware" function:
const logger = (req: Request, res: Response, next: NextFunction): void => {
    console.log(req.url, req.method,req.hostname);
    next();
}


//==> for this: http://localhost:5000/123/12
app.get('/:id/:subid',logger, (req: Request, res: Response) => {
    console.log(req.params);
    res.send('param all!')
})

//==> for tthis=> http://localhost:5000?email=karakib2k18@gmail.com&name=rakib
app.get('/',logger, (req: Request, res: Response) => {
    console.log(req.query);
    console.log(req.query.name);
    console.log(req.query.email);
    res.send('query param!')
})

app.post('/',logger, (req: Request, res: Response) => {
    console.log(req.body);
    res.json({
        message: "suffesfully done"
    })
})

export default app;
```

## 7-9 Routing in express.js

```js
// const express = require('express')
import express, {Request, Response, NextFunction } from 'express';

const app = express();
const port = 3000;

//perser
app.use(express.json());
app.use(express.text());

//use router
const useRouter =  express.Router();
const courseRouter =  express.Router();

app.use("/api/v1/users", useRouter);
app.use("/api/v1/course", courseRouter);

useRouter.get("/create-user", (req: Request, res: Response) => {
    const user = req.body;
    console.log(user);
    res.json({
        success: true,
        message: "user is create successfully",
        data: user,
    })
})

courseRouter.post("/create-course", (req: Request, res: Response) => {
    const course = req.body;
    console.log(course);
    res.json({
        success: true,
        message: "course is create successfully",
        data: course,
    })
})


export default app;
```

## 7-10 express Error Handler part 1

```js
app.get('/',logger,  async(req: Request, res: Response, next: NextFunction) => {
    try {
        res.send(result); //=> here is worng
      } catch (error) {
        next(error); // NEXT diye global middleware a send kore dibo
      }
    console.log(req.body);

})

```

```js
// Error handling GLOBAL middleware
app.use((error: any, req: Request, res: Response, next: NextFunction) => {
    console.log(error);
    if(error){
        res.status(400).json({
            success: false,
            message: "Something went wrong",
        });
    }
  });
```

```js
app.all('*', (req: Request, res: Response) => {
    res.status(400).json({
        success: false,
        message: 'Route is not found',
    });
});
```


```js
app.get('/', logger, async (req: Request, res: Response, next: NextFunction) => {
    try {
        res.send(result); //=> here is worng
    } catch (error) {
        next(error); // NEXT diye global middleware a send kore dibo
    }
    console.log(req.body);

})

app.all('*', (req: Request, res: Response) => {
    res.status(400).json({
        success: false,
        message: 'Route is not found',
    });
});


// Error handling GLOBAL middleware
app.use((error: any, req: Request, res: Response, next: NextFunction) => {
    console.log(error);
    if (error) {
        res.status(400).json({
            success: false,
            message: "Something went wrong",
        });
    }
});
```

---
# Project-1
# Module_8: Mastering the core concepts of mongoose

=> Installation: https://blog.logrocket.com/linting-typescript-eslint-prettier
=> Starter pack: https://github.com/Apollo-Level2-Web-Dev/first-project/tree/first-project-0

=> Github Link: Module 8 :
https://github.com/Apollo-Level2-Web-Dev/first-project/tree/first-project-1

## 8-1 Introduction to mongoose

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wo1jqxbos5x7k4byd2yx.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pkqh0nv0i3w0jek7roof.png)

## 8-2 Installing express , mongoose, typescript, dotenv ,cors

```js
npm init -y
```

1. express
2. mongose
3. typescript
4. cors
5. dotenv to access environment virable

```js
npm install express
npm install mongodb
npm i dotenv
npm install mongoose --save
npm install typescript --save-dev
npm i cors
tsc -init
npm i --save-dev @types/express
npm i --save-dev @types/cors
```

```js
//then to to the tsconfig.json
//find the rootdir and write: "rootDir": "./src", 
//find the outdir and write: "outDir": "./dist",  
//then open a file src and make a file app.ts in this file
//go to the package.json and write "build": "tsc" in scripts.
```

```js
//then do this for create dist file for js
npm run build
//then run js code
node ./dist/app.js
```

```js
//then listen code to server.ts from app.ts
//then go to the mongose and write it in server.ts
import mongoose from 'mongoose';

main().catch(err => console.log(err));

async function main() {
  await mongoose.connect('mongodb://127.0.0.1:27017/test');

  // use `await mongoose.connect('mongodb://user:password@127.0.0.1:27017/test');` if your database has auth enabled
}

```

```js
//then go to the mongoDB atlas and create a database in Connecting with MongoDB Driver and copy this 3. Add your connection string into your application code then save it in .env file

PORT = 5000
DATABASE_URL = mongodb+srv://admin-um:admin12345@cluster0.rp8qrq9.mongodb.net/first-project?retryWrites=true&w=majority
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tpdxatjp6zrxt9568xj8.png)

```
fidning location of the env file
console.log(process.cwd());
rakib@pop-os:~/Documents/first-project$ node ./dist/app.js
/home/rakib/Documents/first-project

```

```js
//src/app/config/index.ts
import dotenv from 'dotenv'
import path from 'path';
dotenv.config({path: path.join(process.cwd(), '.env)')})
export default{
    port: process.env.PORT,
    database_url: process.env.DATABASE_URL,
}

///home/rakib/Documents/first-project
```

## 8-3 Installing eslint, refactor code, fix errors using command

```js
//server.ts
import app from "./app";
import config from "./app/config";
import mongoose from 'mongoose';

main().catch(err => console.log(err));

async function main() {
    try {
        await mongoose.connect(config.database_url as string);

        app.listen(config.port, () => {
            console.log(`Example app listening on port ${config.port}`)
        })
    } catch (err) {
        console.log(err)
    }
}
```

```js
//app.ts
import express,{Application, Response, Request} from 'express'
const app: Application = express()

app.get('/', (req:Request, res:Response) => {
  res.send('Hello World!')
})

console.log(process.cwd());
export default app;
```

---

```js
//istalling eslint
//now to to the tsconfig.json in vscode and paste this code

  "include": ["src"], // which files to compile
  "exclude": ["node_modules"], // which files to skip

//now install this code in command line:
npm install eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin --save-dev
npx eslint --init

```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ri6xtf4sqz9jrq7sn462.png)

---

```js
You’ll find that some files don’t need to be linted at all, such as your dist folder, so you can prevent linting by creating a .eslintignore file and adding the folders or files you want to ignore:

//=> .eslintignore file create
node_modules
dist

// now go to the packeage.json and add this file in script:
    "lint": "eslint src --ignore-path .eslintignore --ext .ts",

```

```
//for checking
npx eslint src
// 2nd way
npm run lint
//3rd way
npx eslint src .
//to fix the problem write this command in sciprt
    "lint:fix":"npx eslint src --fix",
to run this write this=>npm run lint:fix
```

```js
// go to the eslint.json and add this file in the last
    "rules": {
        "no-unused-vars": "error",
        "no-unused-expressions": "error",
        "prefer-const": "error",
        "no-console": "warn",
        "no-undefined": "error"
    },
    "globals": {
        "dataLayer": "readonly"
    }
```

```js
npm run lint
```

## 8-4 Install prettierts-node-dev,fix formatting issues

**### Integrating Prettier **
Run the following command in the terminal:

```js
npm install --save-dev prettier
```

```
// now a create a file of this=> .prettierrc.json
{
  "semi": true,
  "singleQuote": true

}

```
Next, we are going to start formatting our code using Prettier in the command line:

```js
npx prettier --write src/app.ts
# src/index.ts 37ms
```

// package.json

```js
{
  // ...
  "scripts": {
  // ...others code..
    "prettier": "prettier --ignore-path .gitignore --write \"./src/**/*.+(js|ts|json)\"",
  },
  // ...
}

```

```js
//to run prettier
npm run prettier

```

```
// settings.json =>tthis is vscode setting then paste
{
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnSave": true,
  ...
}

```
=>install direct extesnion app

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/khbfvirerhbtej9n97b1.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ua9jq3ub20qsuxaw9o9g.png)

**Avoiding conflicts when working with ESLint and Prettier
**

```js
npm install --save-dev eslint-config-prettier
```

```
// .eslintrc
{
  // HERE and relace with previous estends
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
    "prettier"
  ],
}

```

```
  "scripts": {
    "prettier": "prettier --ignore-path .gitignore --write \"./src/**/*.+(js|ts|json)\"",
    "prettier:fix": "npx prettier --write src",
  },

```

```
npm run prettier:fix
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uio9fqhl50spskj1tkwn.png)

```js
npm run build
```

```js
// first npm run build, then do node ./dist/server.js, its so boring, so we will write a snipted to do this easily

//now isntall ts-node-dev => for making development faster
npm i ts-node-dev 
npm i ts-node-dev --save-dev

//auto response and making transparent
ts-node-dev --respawn --transpile-only src/server.ts
```

```js
//in package.json
"scripts": {
    "start:prod": "node ./dist/server.js",
    "start:dev": "ts-node-dev --respawn --transpile-only src/server.ts",
    "build": "tsc",
```

```js
// .env file for developemnt
NODE_ENV= development
PORT=5000
DATABASE_URL= mongodb+srv://admin:admin@cluster0.rp8qrq9.mongodb.net/?retryWrites=true&w=majority
```

## 8-5 Software design pattern , mvc vs modular, create an interface


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5jfny16ly9obm6v8fpt8.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tiyj1npmv8gd9mdd6wws.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d1ggtqgdnmhmnivg19g1.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ddvn1bkd81clxl7gwhr3.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/clhfng5m8hss8zyn1uva.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q66xwlv2ydknhkcbvrkz.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/clj4lfo5mwo23nleeyj5.png)

=> go to this site: https://mongoosejs.com/docs/typescript.html

---

## 8-8 Create route , service and controller

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j5m0y8ps4o0z7qc19cu4.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/runebmcptvtrc653tr77.png)


# Advanced CRUD with express, mongoose and typescript 

## 9-1 Introduction to validation

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rb3hwh8n3ihp8kb318ig.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/632b6inz0n5xemtmtrcm.png)

## 9-2 How to do custom validation


## 9-3 How to validate using validator and Joi package

```
npm i validator
npm i -D @types/validator
import validator from 'validator';
```

```
import validator from 'validator';
```

```
    validate: {
      validator: function (value: string) {
        // Capitalize the first letter and check if it remains the same
        const firstNameStr = value.charAt(0).toUpperCase() + value.slice(1);
        return firstNameStr === value;
      },
      message: '{VALUE} is not in capitalized format',
    },
```

```
    validate: {
      validator: (value: string) => validator.isEmail(value),
      message: '{VALUE} is not valid',
    },
```
**_Joi_**
```
npm i joi
import Joi from 'joi';

```

```
    if (error) {
      res.status(500).json({
        success: false,
        message: 'joi validation went wrong',
        data: error.details,
      });
    }
```

```
    const { student: studentData } = req.body;

    // data validation using joy
    const { error, value } = studentValidationSchema.validate(studentData);
    //will call service funditon to send this data
    const result = await StudentServices.createStudentIntoDB(value);
    // // console.log({ error }, { value });

    if (error) {
      res.status(500).json({
        success: false,
        message: 'joi validation went wrong',
        data: error.details,
      });
    }
```

## 9-5 How to validate using zod

```
npm install zod 
```

```
    const { student: studentData } = req.body;

    //------------------------------
    // //==> data validation using zod=> IMPORTANT
    const zodvalidatedData = studentValidationSchema.parse(studentData);

    const result = await StudentServices.createStudentIntoDB(zodvalidatedData);

    //-------------------------------
```

## 9-6 Implement a custom instance method

```
const createStudentIntoDB = async (studentData: Student) => {
  //   //by noramal as usal method
  // const result = await studentModel.create(studentData);

  //static method create
  const student = new studentModel(studentData);
  const result = await student.save(); //built in instance
  return result;
};
```

```
export type StudentMethods = {
  isUserExits(id: string): Promise<Student>;
};

export type StudentModel = Model<
  Student,
  Record<string, never>,
  StudentMethods
>;

```

## 9-7 Implement a custom static method

```
//creating a custom static method

export interface StudentModel extends Model<TStudent> {
  // eslint-disable-next-line no-unused-vars
  isUserExists(id: string): Promise<TStudent | null>;
}
```

```
const studentSchema = new Schema<TStudent, StudentModel>(

```

```
// create cusitom static method

studentSchema.statics.isUserExists = async function (id: string) {
  const existingUser = await Student.findOne({ id });
  return existingUser;
};
```

```
  // 9-7 Implement a custom static method
  if (await Student.isUserExists(studentData.id)) {
    throw new Error('user already registerd');
  }
  const result = await Student.create(studentData);
  return result;
```

## 9-8 Implement mongoose middleware part

```js
npm i bcrypt
npm i -D @types/bcrypt
```

```js
BCRYPT_SALT_ROUND=12 //.env file
 bycrypt_salt_rounds: process.env.BCRYPT_SALT_ROUND, //.config file

```

```js
//post save middleware 
studentSchema.post('save', function (doc, next) {
  doc.password = '';
  // console.log('post hook: we save our data', this);
  next();
});

//query find middleware
studentSchema.pre('find', function (next) {
  // console.log('post hook: we save our data', this);
  this.find({ isDeleted: { $ne: true } });

  next();
});

//findOne
studentSchema.pre('findOne', function (next) {
  // console.log('post hook: we save our data', this);
  this.find({ isDeleted: { $ne: true } });

  next();
});

//aggregate
studentSchema.pre('aggregate', function (next) {
  // console.log('post hook: we save our data', this);
  this.pipeline().unshift({ $match: { isDeleted: { $ne: true } } });

  next();
});
```

```js
//Encrypt & pre save middleware/hook: will work on create on save function
studentSchema.pre('save', async function (next) {
  // console.log('pre hook: we save our data', this);

  //hashing password and save into DB
  // eslint-disable-next-line @typescript-eslint/no-this-alias
  const user = this; // documents
  user.password = await bcrypt.hash(
    user.password,
    Number(config.bycrypt_salt_rounds),
  );
  next();
});

```

## 9-9 How to implement delete data in another way

```
//post save middleware 
studentSchema.post('save', function (doc, next) {
  doc.password = '';
  // console.log('post hook: we save our data', this);
  next();
});

```

## 9-10 How to implement query middlewares

```
  this.find({ isDeleted: { $ne: true } });
```

```
//aggregate
studentSchema.pre('aggregate', function (next) {
  // console.log('post hook: we save our data', this);
  this.pipeline().unshift({ $match: { isDeleted: { $ne: true } } });

  next();
});
```

```
const getSignleStudentsFromBD = async (id: string) => {
  //aggregate system
  const result = await Student.aggregate([{ $match: { id: id } }]);
  return result;
};

```

## 9-11 Mongoose Virtuals and Module Summary

```
const opts = { toJSON: { virtuals: true } };
const userSchema = mongoose.Schema({
  _id: Number,
  email: String
}, opts);
```

```
  { toJSON: { virtuals: true } },
);

//virtual
studentSchema.virtual('FullName').get(function () {
  return `${this.name.firstName} ${this.name.middleName} ${this.name.lastName}`;
});

```

---

---