If tutorials available on this website are helpful for you, please whitelist this website in your ad blocker😭 or Donate to help us ❤️ pay for the web hosting to keep the website running.
NestJS में MySQL के साथ raw SQL
queries run करना तब काम आता है जब आपको complex SQL queries execute करनी हूँ जो आपके ORM
(Object Relational Mapping) से efficiently handle नहीं हो पा रही हो।
TypeORM जो एक ORM है, generally आपको abstraction provide करता है ताकि आप SQL queries को object-oriented
तरीके से लिख सकें, लेकिन कभी-कभी आपको direct raw SQL queries लिखने कि need होती है, especially जब आपको complex joins, performance tuning, या non-standard SQL operations perform करनी हो।
इस topic में हम देखेंगे कि कैसे NestJS में MySQL के साथ raw SQL queries run करते हैं using TypeORM
, और इसके फायदे और methods को detail में समझेंगे।
Raw queries का use तब करना चाहिए जब -
Complex Queries : आपको ऐसी complex queries लिखनी हो जो ORM easily handle नहीं कर सकता, जैसे multi-table joins या custom aggregation queries.
Performance Optimizations : अगर आपको query performance को optimize करना हो तो raw SQL queries का use करना better होता है।
Database-Specific Functions : जैसे triggers, stored procedures, या ऐसे database-specific operations जो ORM support नहीं करता।
●●●
make sure , आपने mysql2
package install कर लिया है अपने project में।
File : src/app.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UserModule } from './user/user.module';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'mysql',
host: 'localhost',
port: 3306,
username: 'root',
password: 'password',
database: 'nest_db',
entities: [__dirname + '/**/*.entity{.ts,.js}'],
synchronize: true, // Development ke liye synchronize true rakhein
}),
UserModule,
],
})
export class AppModule {}
चलिए अब हम एक SQLHelper
class बनाते हैं जो raw queries को run करेगी। इस class में हम एक generic method runQuery()
बनाएंगे जो SQL query को execute करेगा।
File : src/common/sql.helper.ts
import { Injectable } from '@nestjs/common';
import { DataSource } from 'typeorm';
@Injectable()
export class SQLHelper {
constructor(private dataSource: DataSource) {}
// Generic function to run any raw SQL query
async runQuery(query: string, parameters?: any[]): Promise<any> {
try {
const result = await this.dataSource.query(query, parameters || []);
return result;
} catch (error) {
console.error('Error executing query:', error);
throw new Error('Database query failed');
}
}
}
यहां
runQuery(query: string, parameters?: any[])
एक generic function है जो किसी भी SQL query को execute करेगा।
parameters एक optional array है जो query के dynamic values को inject करने के लिए use होता है (ताकि SQL injection से बच सकें).
try-catch
block का use करके errors को handle किया गया है।
●●●
अब जब हमने SQLHelper
class बनाली है, तो हम इस class का use करके अलग-अलग SQL queries को run कर सकते हैं बिना हर बार services लिखे।
चलिए अब हम UserService
को हटा कर directly SQLHelper का use किसी controller या किसी दूसरी service में कर करते हैं।
File : src/user/user.controller.ts
import { Controller, Get, Post, Param, Body } from '@nestjs/common';
import { SQLHelper } from '../common/sql.helper';
@Controller('users')
export class UserController {
constructor(private readonly sqlHelper: SQLHelper) {}
// GET all users using SQLHelper
@Get()
async getAllUsers() {
const query = 'SELECT * FROM users';
return this.sqlHelper.runQuery(query);
}
// GET user by ID using SQLHelper
@Get(':id')
async getUserById(@Param('id') id: number) {
const query = 'SELECT * FROM users WHERE id = ?';
return this.sqlHelper.runQuery(query, [id]);
}
// POST: Insert new user using SQLHelper
@Post()
async insertUser(@Body() userData: { name: string; email: string; age: number }) {
const query = 'INSERT INTO users (name, email, age) VALUES (?, ?, ?)';
return this.sqlHelper.runQuery(query, [userData.name, userData.email, userData.age]);
}
}
Example में हमने SQLHelper
का use करके queries run की हैं जो centralized query execution को handle करती है। getAllUsers(), getUserById(), और insertUser() methods ने directly runQuery()
को call किया है।
इस तरीके से आप सभी SQL operations को एक जगह से manage कर सकते हैं, जो code को simple और clean रखता है।
●●●
Helper class का use real-world scenarios में काफी फायदेमंद होता है जब आपको multiple services में similar queries लिखनी होती हैं या आपको queries को dynamically create करना होता है।
अब हम एक example देखते हैं जिसमे dynamic filtering और sorting को SQLHelper के साथ implement करते हैं।
File : src/user/user.controller.ts
import { Controller, Get, Query } from '@nestjs/common';
import { SQLHelper } from '../common/sql.helper';
@Controller('users')
export class UserController {
constructor(private readonly sqlHelper: SQLHelper) {}
// GET users with optional filters and sorting
@Get('search')
async searchUsers(
@Query('name') name?: string,
@Query('age') age?: number,
@Query('sort') sort?: string
) {
let query = 'SELECT * FROM users WHERE 1=1';
const parameters = [];
if (name) {
query += ' AND name LIKE ?';
parameters.push(`%${name}%`);
}
if (age) {
query += ' AND age = ?';
parameters.push(age);
}
if (sort) {
query += ` ORDER BY ${sort}`;
}
return this.sqlHelper.runQuery(query, parameters);
}
}
यहां
Dynamic filtering (name, age) और sorting को handle करने के लिए query को dynamically construct किया गया है।
SQLHelper
के through query run कि गयी है और results को return किया गया है।
●●●
जब आप NestJS में this.dataSource.query()
function का use करते हैं तो raw SQL queries run करने के लिए, यह function Promise
return करता है जो query के execution का result return करता है।
जब आप SELECT
query run करते हैं, तो यह function एक array of objects return करता है, जिसमें हर object एक row (record) को represent करता है।
हर row का data key:value
pair के form में होता है, जिसमें keys आपके table के column names होते हैं, और values वो specific record के values होते हैं।
const users = await this.dataSource.query('SELECT * FROM users');
console.log(users);
Output
[ { "id": 1, "name": "John", "email": "john@example.com", "age": 30 }, { "id": 2, "name": "Jane", "email": "jane@example.com", "age": 25 } ]
जब आप INSERT, UPDATE, या DELETE queries run करते हैं, तो this.dataSource.query()
function query के execution का metadata return करता है, जो query का status, affected rows, etc. को represent करता है।
const result = await this.dataSource.query(
'INSERT INTO users (name, email, age) VALUES (?, ?, ?)',
['Alice', 'alice@example.com', 28]
);
console.log(result);
Output
{ "fieldCount": 0, "affectedRows": 1, "insertId": 3, // ID of the newly inserted row "serverStatus": 2, "warningCount": 0, "message": "", "protocol41": true, "changedRows": 0 }
●●●
Centralized Query Execution : एक helper class का use करना एक smart approach है जो raw SQL queries को centralize करता है। यह आपको code re-usability और maintainability में help करता है।
Error Handling : हर query के execution के साथ error handling जरूर लगाएं। अगर कोई query fail होती है तो proper logging और error messages दिखाने का ध्यान रखें।
Use Parameterized Queries : Parameterized queries का use करना SQL injection attacks से बचने का best तरीका है. हर dynamic value को parameterize करें ताकि query safe हो।
Optimize Complex Queries : जब complex SQL queries लिख रहे हो, तो ensure करें कि queries optimized हूँ. Indexing और query execution plans का ध्यान रखें।
Modular Structure : SQLHelper को modular और independent रखें ताकि आप इससे easily reuse कर सकें across multiple modules और services.