Complex Queries in TypeORM
TypeORM হল একটি শক্তিশালী ORM (Object-Relational Mapping) লাইব্রেরি যা JavaScript এবং TypeScript ডেভেলপমেন্টের জন্য ব্যবহৃত হয়। এটি SQL কোড লিখা ছাড়াই ডেটাবেসের সাথে কাজ করার সুবিধা প্রদান করে, তবে কখনও কখনও আপনাকে Complex Queries, যেমন JOIN, Subqueries ইত্যাদি প্রয়োজন হতে পারে। TypeORM-এ এই ধরনের কুয়েরি তৈরি করতে QueryBuilder ব্যবহার করা হয়।
এই গাইডে আমরা JOIN এবং Subqueries এর মাধ্যমে Complex Queries তৈরি করার পদ্ধতি সম্পর্কে আলোচনা করব।
১. JOIN ব্যবহার করে Complex Queries তৈরি করা
TypeORM-এ JOIN অপারেশন করতে, আমরা createQueryBuilder() ব্যবহার করি। JOIN ব্যবহার করলে একাধিক টেবিলের মধ্যে সম্পর্ক স্থাপন করতে এবং তাদের ডেটা একত্রে নিয়ে আসতে সাহায্য করে।
একটি সাধারন JOIN উদাহরণ:
ধরা যাক, আমরা দুটি টেবিল User এবং Profile এর মধ্যে একটি One-to-One সম্পর্ক তৈরি করেছি, এবং আমরা দুইটি টেবিলের ডেটা একত্রে আনতে চাই।
import { Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn } from "typeorm";
import { Profile } from "./Profile";
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@OneToOne(() => Profile)
@JoinColumn()
profile: Profile;
}
@Entity()
export class Profile {
@PrimaryGeneratedColumn()
id: number;
@Column()
bio: string;
}
এখানে, User এবং Profile এর মধ্যে One-to-One সম্পর্ক রয়েছে।
JOIN Query Example:
import { createConnection } from "typeorm";
import { User } from "./entity/User";
import { Profile } from "./entity/Profile";
createConnection().then(async connection => {
const userRepository = connection.getRepository(User);
const usersWithProfile = await userRepository
.createQueryBuilder("user")
.leftJoinAndSelect("user.profile", "profile") // Performing LEFT JOIN with Profile table
.getMany();
console.log(usersWithProfile);
}).catch(error => console.log(error));
এখানে, leftJoinAndSelect() ব্যবহার করে আমরা User টেবিলের সাথে Profile টেবিলকে LEFT JOIN করেছি এবং দুইটি টেবিলের ডেটা একত্রে রিটার্ন করেছি। getMany() ব্যবহার করে আমরা একাধিক রেকর্ড পাচ্ছি।
২. Subqueries ব্যবহার করে Complex Queries তৈরি করা
Subqueries হল এমন কুয়েরি যা অন্য কুয়েরির মধ্যে ব্যবহার করা হয়। TypeORM-এ Subquery তৈরি করার জন্য আমরা subQuery() মেথড ব্যবহার করতে পারি।
Subquery উদাহরণ:
ধরা যাক, আমাদের কাছে একটি Post এবং Comment টেবিল আছে এবং আমরা এমন একটি কুয়েরি তৈরি করতে চাই যেখানে একটি Post এর মোট কমেন্ট সংখ্যা রিটার্ন হবে।
import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from "typeorm";
import { Comment } from "./Comment";
@Entity()
export class Post {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@OneToMany(() => Comment, comment => comment.post)
comments: Comment[];
}
@Entity()
export class Comment {
@PrimaryGeneratedColumn()
id: number;
@Column()
content: string;
@ManyToOne(() => Post, post => post.comments)
post: Post;
}
এখানে, Post এবং Comment এর মধ্যে One-to-Many সম্পর্ক রয়েছে।
Subquery Query Example:
import { createConnection } from "typeorm";
import { Post } from "./entity/Post";
import { Comment } from "./entity/Comment";
createConnection().then(async connection => {
const postRepository = connection.getRepository(Post);
const postsWithCommentCount = await postRepository
.createQueryBuilder("post")
.addSelect(subQuery => {
return subQuery
.select("COUNT(comment.id)", "commentCount")
.from(Comment, "comment")
.where("comment.postId = post.id");
}, "commentCount")
.getMany();
console.log(postsWithCommentCount);
}).catch(error => console.log(error));
এখানে, addSelect() ব্যবহার করে একটি Subquery যুক্ত করা হয়েছে, যেখানে Comment টেবিলের postId এর ভিত্তিতে কমেন্ট সংখ্যা গোনা হয়েছে এবং সেটি commentCount নামে রিটার্ন করা হয়েছে।
৩. Complex WHERE Clauses এবং GROUP BY ব্যবহার করা
TypeORM-এ WHERE ক্লজ এবং GROUP BY ব্যবহার করে আরও জটিল কুয়েরি তৈরি করা যেতে পারে।
WHERE এবং GROUP BY Example:
createConnection().then(async connection => {
const postRepository = connection.getRepository(Post);
const posts = await postRepository
.createQueryBuilder("post")
.leftJoinAndSelect("post.comments", "comment")
.where("post.title LIKE :title", { title: '%JavaScript%' })
.groupBy("post.id")
.having("COUNT(comment.id) > :count", { count: 5 })
.getMany();
console.log(posts);
}).catch(error => console.log(error));
এখানে, আমরা LEFT JOIN এর মাধ্যমে Comment টেবিলের সাথে যুক্ত করেছি এবং WHERE এবং HAVING ক্লজ ব্যবহার করে title এর ভিত্তিতে ফিল্টার এবং কমেন্টের সংখ্যা চেক করেছি। groupBy() এবং having() ব্যবহার করে পোস্টগুলোর উপর গ্রুপিং এবং ফিল্টার করা হয়েছে।
৪. Query Parameters (Parameterized Queries) ব্যবহার করা
Parameterized Queries হল এমন কুয়েরি যেখানে ইউজারের ইনপুট সরাসরি SQL কুয়েরির অংশ না হয়ে, তার পরিবর্তে প্যারামিটার হিসেবে ব্যবহৃত হয়। এটি SQL ইনজেকশন প্রতিরোধে সাহায্য করে।
Parameterized Query Example:
createConnection().then(async connection => {
const userRepository = connection.getRepository(User);
const user = await userRepository
.createQueryBuilder("user")
.where("user.name = :name", { name: "John Doe" })
.getOne();
console.log(user);
}).catch(error => console.log(error));
এখানে, :name প্যারামিটার ব্যবহার করে SQL কুয়েরি নিরাপদভাবে পরিচালনা করা হয়েছে এবং getOne() ব্যবহার করে শুধুমাত্র একটিমাত্র রেকর্ড পাওয়া যাবে।
সারাংশ
TypeORM-এ Complex Queries তৈরি করা সহজ এবং শক্তিশালী। আপনি JOIN, Subqueries, WHERE, GROUP BY, এবং HAVING ক্লজের মাধ্যমে জটিল কুয়েরি তৈরি করতে পারেন। QueryBuilder ব্যবহার করে আপনি কাস্টম কুয়েরি তৈরি করতে এবং SQL কুয়েরি অপারেশনগুলি নিরাপদভাবে পরিচালনা করতে পারেন। TypeORM এর এই শক্তিশালী কুয়েরি ফিচারগুলি ডেটাবেসের সাথে সহজ এবং কার্যকরীভাবে যোগাযোগ করতে সহায়তা করে।