TypeORM এর মাধ্যমে Advanced Querying
TypeORM হল একটি Object-Relational Mapping (ORM) লাইব্রেরি যা জাভাস্ক্রিপ্ট এবং টাইপস্ক্রিপ্টে ডেটাবেস অপারেশন সহজ করে তোলে। এর সাহায্যে আপনি SQL কোড লেখার প্রয়োজন ছাড়াই ডেটাবেসের সাথে ইন্টারঅ্যাক্ট করতে পারেন। TypeORM সাধারণ CRUD (Create, Read, Update, Delete) অপারেশনগুলি সহজে পরিচালনা করতে সাহায্য করে, তবে এর ক্ষমতা Advanced Querying এর জন্যও বেশ শক্তিশালী। QueryBuilder ব্যবহার করে TypeORM-এ জটিল কুয়েরি তৈরি করা যায়।
এখানে আমরা Advanced Querying এবং Relations সম্পর্কে আলোচনা করব।
Advanced Querying in TypeORM
TypeORM-এ Advanced Querying করতে QueryBuilder ব্যবহার করা হয়। QueryBuilder আপনাকে SQL এর মতো কাস্টম কুয়েরি তৈরি করতে সহায়তা করে। এর মাধ্যমে আপনি জটিল কুয়েরি তৈরি করতে পারেন, যেমন JOIN অপারেশন, GROUP BY, HAVING, ORDER BY, এবং LIMIT ইত্যাদি।
১. QueryBuilder ব্যবহার করে Basic Query
createQueryBuilder() মেথড দিয়ে TypeORM-এ কাস্টম কুয়েরি তৈরি করা যায়। এটি WHERE, SELECT, JOIN ইত্যাদি SQL অপারেশনগুলি সহজে ব্যবহার করতে সাহায্য করে।
উদাহরণ:
const users = await connection
.getRepository(User)
.createQueryBuilder("user")
.where("user.age > :age", { age: 25 })
.getMany();
console.log(users);
এখানে, createQueryBuilder() ব্যবহার করে age এর উপর ফিল্টার প্রয়োগ করা হয়েছে এবং ব্যবহারকারী whose age ২৫ এর বেশি তাদেরকে রিটার্ন করা হয়েছে।
২. JOIN ব্যবহার করা
TypeORM-এ বিভিন্ন টেবিলের মধ্যে সম্পর্ক প্রতিষ্ঠা করতে JOIN ব্যবহার করা যায়। TypeORM এর QueryBuilder সহজেই INNER JOIN, LEFT JOIN ইত্যাদি কাস্টম JOIN তৈরি করতে সক্ষম।
উদাহরণ:
ধরা যাক, আমাদের User এবং Post টেবিল রয়েছে। আমরা User এর সাথে সম্পর্কিত Post গুলোকেও লোড করতে চাই।
const usersWithPosts = await connection
.getRepository(User)
.createQueryBuilder("user")
.leftJoinAndSelect("user.posts", "post")
.getMany();
console.log(usersWithPosts);
এখানে, leftJoinAndSelect() ব্যবহার করে User টেবিলের সাথে Post টেবিলের সম্পর্কিত ডেটা লোড করা হয়েছে।
৩. Group By এবং Having ব্যবহার করা
TypeORM QueryBuilder দিয়ে GROUP BY এবং HAVING এর মতো SQL ফিচারও ব্যবহার করা যায়। এটি ডেটার উপর গ্রুপিং এবং শর্তযুক্ত ফিল্টারিং করতে সহায়তা করে।
উদাহরণ:
const userCountByAge = await connection
.getRepository(User)
.createQueryBuilder("user")
.select("user.age")
.addSelect("COUNT(user.id)", "userCount")
.groupBy("user.age")
.having("userCount > :minCount", { minCount: 1 })
.getRawMany();
console.log(userCountByAge);
এখানে, আমরা age এর ভিত্তিতে User গুলোকে গ্রুপ করেছি এবং প্রতিটি গ্রুপে ১ জনের বেশি ইউজার রয়েছে কিনা তা যাচাই করেছি।
৪. Order By এবং Limit ব্যবহার করা
TypeORM-এ ORDER BY এবং LIMIT অপারেশন ব্যবহারের মাধ্যমে ডেটা সাজানো এবং সীমিত করা যায়।
উদাহরণ:
const recentPosts = await connection
.getRepository(Post)
.createQueryBuilder("post")
.orderBy("post.createdAt", "DESC")
.limit(5)
.getMany();
console.log(recentPosts);
এখানে, orderBy() এবং limit() ব্যবহার করে সর্বশেষ ৫টি Post ডেটা রিটার্ন করা হয়েছে।
TypeORM Relations: Relationship Types
TypeORM-এ Relations ডেকোরেটরের মাধ্যমে একাধিক টেবিলের মধ্যে সম্পর্ক তৈরি করা হয়। এই সম্পর্কগুলো One-to-One, One-to-Many, Many-to-One, এবং Many-to-Many হতে পারে।
১. One-to-One Relation
One-to-One সম্পর্ক তৈরি করতে @OneToOne এবং @JoinColumn ডেকোরেটর ব্যবহার করা হয়। এই সম্পর্কের মধ্যে একটি টেবিলের একটি রেকর্ড অন্য টেবিলের একটির সাথে সম্পর্কিত থাকে।
উদাহরণ:
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@OneToOne(type => Profile)
@JoinColumn()
profile: Profile;
}
@Entity()
export class Profile {
@PrimaryGeneratedColumn()
id: number;
@Column()
bio: string;
}
এখানে, User টেবিলের একটি রেকর্ডের সাথে Profile টেবিলের একটিই রেকর্ড সম্পর্কিত।
২. One-to-Many Relation
One-to-Many সম্পর্ক তৈরি করতে @OneToMany এবং @ManyToOne ডেকোরেটর ব্যবহার করা হয়। এখানে একটি টেবিলের একটি রেকর্ড একাধিক রেকর্ডের সাথে সম্পর্কিত থাকে।
উদাহরণ:
@Entity()
export class Category {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@OneToMany(type => Product, product => product.category)
products: Product[];
}
@Entity()
export class Product {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@ManyToOne(type => Category, category => category.products)
category: Category;
}
এখানে, Category এর একটি রেকর্ড একাধিক Product রেকর্ডের সাথে সম্পর্কিত।
৩. Many-to-Many Relation
Many-to-Many সম্পর্ক তৈরি করতে @ManyToMany এবং @JoinTable ডেকোরেটর ব্যবহার করা হয়। এখানে একাধিক রেকর্ড একাধিক রেকর্ডের সাথে সম্পর্কিত থাকে।
উদাহরণ:
@Entity()
export class Student {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@ManyToMany(type => Course)
@JoinTable()
courses: Course[];
}
@Entity()
export class Course {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@ManyToMany(type => Student)
students: Student[];
}
এখানে, Student এবং Course এর মধ্যে Many-to-Many সম্পর্ক তৈরি করা হয়েছে।
QueryBuilder এবং Relations একত্রিত করা
TypeORM-এ QueryBuilder ব্যবহার করে আপনি সম্পর্কিত টেবিলগুলির উপর কাস্টম কুয়েরি চালাতে পারেন। আপনি leftJoinAndSelect() অথবা innerJoinAndSelect() ব্যবহার করে সম্পর্কিত ডেটা লোড করতে পারেন।
উদাহরণ:
const studentsWithCourses = await connection
.getRepository(Student)
.createQueryBuilder("student")
.leftJoinAndSelect("student.courses", "course")
.getMany();
console.log(studentsWithCourses);
এখানে, leftJoinAndSelect() ব্যবহার করে আমরা Student টেবিলের সাথে সম্পর্কিত Course গুলো লোড করেছি।
সারাংশ
Advanced Querying TypeORM-এ QueryBuilder এর মাধ্যমে জটিল কুয়েরি তৈরি করা যায়, যেমন JOIN, GROUP BY, ORDER BY, LIMIT ইত্যাদি অপারেশন। TypeORM-এ Relations ডেকোরেটর ব্যবহার করে আপনি একাধিক টেবিলের মধ্যে সম্পর্ক তৈরি করতে পারেন এবং সেই সম্পর্কের উপর কাস্টম কুয়েরি চালাতে পারেন। TypeORM এর QueryBuilder এবং Relations এর ব্যবহার ডেটাবেস ম্যানিপুলেশন এবং কাস্টম কুয়েরি পরিচালনার জন্য অত্যন্ত শক্তিশালী টুল সরবরাহ করে।
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 এর এই শক্তিশালী কুয়েরি ফিচারগুলি ডেটাবেসের সাথে সহজ এবং কার্যকরীভাবে যোগাযোগ করতে সহায়তা করে।
Relation Mapping in TypeORM
Relation Mapping TypeORM-এ ডেটাবেস টেবিলগুলির মধ্যে সম্পর্ক তৈরি করার প্রক্রিয়া। TypeORM আপনার JavaScript বা TypeScript ক্লাস (এন্টিটি) গুলিকে ডেটাবেস টেবিলের সাথে ম্যাপ করে, এবং সম্পর্কিত এন্টিটির মধ্যে ডেটা সম্পর্কিত সমস্ত অপারেশন পরিচালনা করার জন্য বিভিন্ন ডেকোরেটর (decorators) ব্যবহার করতে সাহায্য করে।
TypeORM-এ সাধারণত চারটি ধরনের সম্পর্ক থাকে:
- One-to-One Relation: এক টেবিলের একটি রেকর্ড অন্য টেবিলের একটির সাথে সম্পর্কিত।
- One-to-Many Relation: এক টেবিলের একটি রেকর্ড অনেক টেবিলের রেকর্ডের সাথে সম্পর্কিত।
- Many-to-One Relation: অনেক টেবিলের রেকর্ড এক টেবিলের একটি রেকর্ডের সাথে সম্পর্কিত।
- Many-to-Many Relation: অনেক টেবিলের রেকর্ড অন্য অনেক টেবিলের রেকর্ডের সাথে সম্পর্কিত।
TypeORM এই সম্পর্কগুলি তৈরি করতে @OneToOne, @OneToMany, @ManyToOne, @ManyToMany ডেকোরেটর সরবরাহ করে।
1. One-to-One Relation Mapping
একটি One-to-One সম্পর্ক তৈরি করতে, TypeORM এ @OneToOne এবং @JoinColumn ডেকোরেটর ব্যবহার করা হয়। এখানে, দুটি টেবিলের মধ্যে প্রতিটি রেকর্ডের একটি সম্পর্ক থাকবে।
উদাহরণ: User এবং Profile সম্পর্ক
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 সম্পর্ক তৈরি হয়েছে। @JoinColumn ডেকোরেটর ব্যবহার করা হয়েছে যাতে সম্পর্কিত টেবিলের মধ্যে কনটেক্সট এবং সম্পর্ক সঠিকভাবে চিহ্নিত হয়।
2. One-to-Many and Many-to-One Relation Mapping
One-to-Many এবং Many-to-One সম্পর্ক সাধারণত একে অপরের সাথে জড়িত থাকে। এখানে একটি One-to-Many সম্পর্ক তৈরি করা হয়েছে যেখানে এক Category টেবিলের একটি রেকর্ড একাধিক Product টেবিলের রেকর্ডের সাথে সম্পর্কিত।
উদাহরণ: Category এবং Product সম্পর্ক
import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from "typeorm";
import { Product } from "./Product";
@Entity()
export class Category {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@OneToMany(() => Product, product => product.category)
products: Product[];
}
@Entity()
export class Product {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@ManyToOne(() => Category, category => category.products)
category: Category;
}
এখানে, Category এবং Product টেবিলের মধ্যে One-to-Many এবং Many-to-One সম্পর্ক স্থাপন করা হয়েছে। @ManyToOne ডেকোরেটর Product টেবিলের ভিতরে ব্যবহার করা হয়েছে, যাতে এটি Category টেবিলের সাথে সম্পর্কিত থাকে।
3. Many-to-Many Relation Mapping
Many-to-Many সম্পর্ক একাধিক রেকর্ডকে একাধিক রেকর্ডের সাথে সম্পর্কিত করে। Many-to-Many সম্পর্ক তৈরি করতে @ManyToMany এবং @JoinTable ডেকোরেটর ব্যবহার করা হয়।
উদাহরণ: Student এবং Course সম্পর্ক
import { Entity, PrimaryGeneratedColumn, Column, ManyToMany, JoinTable } from "typeorm";
import { Course } from "./Course";
@Entity()
export class Student {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@ManyToMany(() => Course)
@JoinTable()
courses: Course[];
}
@Entity()
export class Course {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@ManyToMany(() => Student)
students: Student[];
}
এখানে, Student এবং Course টেবিলের মধ্যে Many-to-Many সম্পর্ক তৈরি করা হয়েছে। @JoinTable ডেকোরেটরটি একটি মধ্যবর্তী টেবিল তৈরি করতে ব্যবহৃত হয়, যেটি দুই টেবিলের মধ্যে সম্পর্ক স্থাপন করে।
Nested Queries in TypeORM
Nested Queries হল এমন কুয়েরি যেখানে একটি সাব-কুয়েরি (subquery) অন্য কুয়েরির মধ্যে ব্যবহার করা হয়। TypeORM এ QueryBuilder ব্যবহার করে আপনি nested queries তৈরি করতে পারেন।
TypeORM-এ QueryBuilder এর মাধ্যমে আপনি জটিল কুয়েরি তৈরি করতে পারেন, যার মধ্যে INNER JOIN, LEFT JOIN, WHERE শর্তাবলী, এবং subqueries অন্তর্ভুক্ত থাকে।
১. Simple Nested Query with QueryBuilder
import { createQueryBuilder } from "typeorm";
import { User } from "./User";
async function getUserData() {
const user = await createQueryBuilder("user")
.leftJoinAndSelect("user.profile", "profile")
.where("user.id = :id", { id: 1 })
.getOne();
console.log(user);
}
এখানে, LEFT JOIN ব্যবহার করা হয়েছে, যাতে User এবং তার সম্পর্কিত Profile টেবিলের ডেটা একসাথে পাওয়া যায়।
২. Using Subqueries with QueryBuilder
import { createQueryBuilder } from "typeorm";
import { User } from "./User";
async function getUserWithPosts() {
const user = await createQueryBuilder("user")
.leftJoin(
subQuery => {
return subQuery
.select("post.title")
.from("post", "post")
.where("post.userId = user.id");
},
"post_titles",
"user.id = post_titles.userId"
)
.getOne();
console.log(user);
}
এখানে একটি subquery ব্যবহার করা হয়েছে, যেখানে Post টেবিলের টাইটেলগুলি বের করা হচ্ছে, যা একটি সাব-কুয়েরি হিসাবে User টেবিলের সাথে যুক্ত।
সারাংশ
TypeORM ডেটাবেস সম্পর্কগুলি সহজে পরিচালনা করার জন্য শক্তিশালী Relation Mapping ফিচার সরবরাহ করে। One-to-One, One-to-Many, Many-to-One, এবং Many-to-Many সম্পর্কগুলি সহজেই TypeORM-এ তৈরি করা যেতে পারে, যার মাধ্যমে ডেটাবেসের মধ্যে সম্পর্কিত তথ্যগুলিকে ম্যাপ করা হয়। একইভাবে, Nested Queries এর মাধ্যমে TypeORM-এ জটিল কুয়েরি তৈরি করা সম্ভব, যেখানে QueryBuilder এবং subqueries ব্যবহার করে ডেটাবেস থেকে নির্দিষ্ট ডেটা বের করা যায়। TypeORM এর এই ফিচারগুলি ডেটাবেস ম্যানিপুলেশন এবং সম্পর্কিত ডেটা সংগ্রহ করা খুবই কার্যকরী ও সহজ করে তোলে।
TypeORM এবং Aggregation/Grouping
TypeORM একটি Object-Relational Mapping (ORM) লাইব্রেরি যা JavaScript এবং TypeScript-এ ডেটাবেস অপারেশন সহজ করে তোলে। ডেটাবেসের সাথে সম্পর্কিত কাজগুলো যেমন CRUD অপারেশন, Relations, Migrations ইত্যাদি TypeORM ব্যবহার করে সহজে করা যায়। এর মধ্যে একটি গুরুত্বপূর্ণ এবং শক্তিশালী ফিচার হল Aggregation এবং Grouping এর মাধ্যমে ডেটা সংগ্রহ এবং বিশ্লেষণ।
Aggregation এবং Grouping ডেটাবেসে ডেটার উপর উন্নত অপারেশন করে যেমন, ডেটার গড়, মোট, সর্বোচ্চ, ন্যূনতম মান বের করা, এবং ডেটাকে গ্রুপ করে উপস্থাপন করা।
Aggregation এবং Grouping TypeORM এ কীভাবে কাজ করে?
TypeORM-এ Aggregation এবং Grouping এর জন্য QueryBuilder ব্যবহার করা হয়, যা কাস্টম কুয়েরি তৈরি করতে সহায়তা করে। TypeORM এর QueryBuilder এর মাধ্যমে আমরা SQL এর GROUP BY, COUNT, SUM, AVG, MIN, MAX ইত্যাদি ফাংশন ব্যবহার করে ডেটার উপর গ্রুপিং এবং অ্যালগোরিদমিক হিসাব করতে পারি।
Aggregation অপারেশন
Aggregation হল ডেটা একত্রিত করার একটি প্রক্রিয়া, যেখানে একটি নির্দিষ্ট মান বের করা হয় যেমন গড় (average), মোট (sum), সর্বোচ্চ (maximum), ন্যূনতম (minimum), বা গণনা (count)।
১. COUNT (গণনা)
COUNT() ফাংশনটি ডেটাবেসের মধ্যে একটি নির্দিষ্ট শর্ত পূরণকারী রেকর্ডের সংখ্যা গণনা করে।
উদাহরণ:
ধরা যাক, আপনার একটি Post টেবিল আছে এবং আপনি জানাতে চান কতগুলো পোস্ট একটি নির্দিষ্ট User এর জন্য রয়েছে:
import { createConnection } from "typeorm";
import { Post } from "./entity/Post";
createConnection().then(async connection => {
const postRepository = connection.getRepository(Post);
const count = await postRepository
.createQueryBuilder("post")
.where("post.userId = :userId", { userId: 1 })
.getCount();
console.log("Total posts by User 1:", count);
}).catch(error => console.log(error));
এখানে, getCount() ফাংশনটি User 1 এর পোস্টের সংখ্যা রিটার্ন করবে।
২. SUM (মোট)
SUM() ফাংশনটি নির্দিষ্ট কলামের সমস্ত মানের মোট যোগফল বের করে।
উদাহরণ:
ধরা যাক, আপনার Order টেবিলের মধ্যে প্রতিটি অর্ডারের মূল্য রয়েছে এবং আপনি মোট অর্ডারের মূল্য বের করতে চান:
import { createConnection } from "typeorm";
import { Order } from "./entity/Order";
createConnection().then(async connection => {
const orderRepository = connection.getRepository(Order);
const totalAmount = await orderRepository
.createQueryBuilder("order")
.select("SUM(order.amount)", "totalAmount")
.getRawOne();
console.log("Total order amount:", totalAmount.totalAmount);
}).catch(error => console.log(error));
এখানে, SUM(order.amount) মোট অর্ডারের পরিমাণ গণনা করে এবং getRawOne() ফলাফল রিটার্ন করে।
৩. AVG (গড়)
AVG() ফাংশনটি একটি নির্দিষ্ট কলামের গড় মান বের করে।
উদাহরণ:
ধরা যাক, আপনি একটি Product টেবিলের মধ্যে দামগুলির গড় বের করতে চান:
import { createConnection } from "typeorm";
import { Product } from "./entity/Product";
createConnection().then(async connection => {
const productRepository = connection.getRepository(Product);
const averagePrice = await productRepository
.createQueryBuilder("product")
.select("AVG(product.price)", "averagePrice")
.getRawOne();
console.log("Average price of products:", averagePrice.averagePrice);
}).catch(error => console.log(error));
এখানে, AVG(product.price) প্রতিটি প্রোডাক্টের দামগুলোর গড় রিটার্ন করবে।
৪. MIN (ন্যূনতম) এবং MAX (সর্বোচ্চ)
MIN() এবং MAX() ফাংশনগুলি একটি কলামের ন্যূনতম এবং সর্বোচ্চ মান বের করে।
উদাহরণ:
import { createConnection } from "typeorm";
import { Product } from "./entity/Product";
createConnection().then(async connection => {
const productRepository = connection.getRepository(Product);
const minPrice = await productRepository
.createQueryBuilder("product")
.select("MIN(product.price)", "minPrice")
.getRawOne();
const maxPrice = await productRepository
.createQueryBuilder("product")
.select("MAX(product.price)", "maxPrice")
.getRawOne();
console.log("Minimum price:", minPrice.minPrice);
console.log("Maximum price:", maxPrice.maxPrice);
}).catch(error => console.log(error));
এখানে, MIN(product.price) এবং MAX(product.price) ফাংশনগুলি প্রোডাক্টের সর্বনিম্ন এবং সর্বোচ্চ দাম রিটার্ন করবে।
Grouping অপারেশন
Grouping হল ডেটাকে বিভিন্ন গ্রুপে ভাগ করে তার উপর বিভিন্ন agregation অপারেশন করা। SQL-এ এটি GROUP BY ক্লজ দিয়ে করা হয়, এবং TypeORM-এ QueryBuilder এর মাধ্যমে এটি বাস্তবায়ন করা হয়।
১. GROUP BY
GROUP BY ডেটাকে এক বা একাধিক কলামের ভিত্তিতে গ্রুপ করে এবং প্রতিটি গ্রুপের উপর aggregation অপারেশন প্রয়োগ করা হয়।
উদাহরণ:
ধরা যাক, আপনি Order টেবিল থেকে প্রতিটি userId এর জন্য মোট অর্ডারের পরিমাণ বের করতে চান:
import { createConnection } from "typeorm";
import { Order } from "./entity/Order";
createConnection().then(async connection => {
const orderRepository = connection.getRepository(Order);
const ordersGroupedByUser = await orderRepository
.createQueryBuilder("order")
.select("order.userId")
.addSelect("SUM(order.amount)", "totalAmount")
.groupBy("order.userId")
.getRawMany();
console.log(ordersGroupedByUser);
}).catch(error => console.log(error));
এখানে, groupBy("order.userId") ব্যবহার করে আমরা প্রতিটি userId এর জন্য SUM(order.amount) গণনা করেছি।
সারাংশ
Aggregation এবং Grouping TypeORM-এ ডেটার উপর শক্তিশালী বিশ্লেষণ করার জন্য ব্যবহৃত হয়। Aggregation অপারেশন যেমন COUNT(), SUM(), AVG(), MIN(), এবং MAX() ডেটার উপর সারণী বা গণনা করতে সাহায্য করে, এবং Grouping অপারেশন ডেটাকে গ্রুপ করে সংশ্লিষ্ট আউটপুট প্রদান করে। TypeORM এর QueryBuilder ব্যবহার করে আপনি এসব অপারেশন সহজেই করতে পারেন, যা আপনার ডেটাবেস অপারেশনকে আরও সহজ, দ্রুত এবং কার্যকরী করে তোলে।
Pagination এবং Sorting কী?
Pagination এবং Sorting হল ডেটাবেসের ডেটা পরিচালনার দুটি গুরুত্বপূর্ণ কৌশল। যখন ডেটাবেসে হাজার হাজার রেকর্ড থাকে, তখন পুরো ডেটা একসাথে রিটার্ন করলে পারফরম্যান্সের সমস্যা হতে পারে। সেক্ষেত্রে Pagination ডেটাকে ছোট ছোট পেজে ভাগ করে দেয় এবং Sorting ডেটাকে নির্দিষ্ট শর্তের উপর ভিত্তি করে সাজায়। TypeORM এ এই দুটি কৌশল খুব সহজভাবে ব্যবহার করা যায়।
TypeORM এ Pagination
Pagination হল ডেটা অ্যাক্সেস করার একটি কৌশল যেখানে আপনি শুধুমাত্র নির্দিষ্ট সংখ্যক রেকর্ড একটি পেজে প্রদর্শন করেন। সাধারণত, আপনি skip() এবং take() মেথডগুলো ব্যবহার করে pagination সেটআপ করতে পারেন।
skip(): কতটি রেকর্ড বাদ দেওয়া হবে তা নির্ধারণ করে।take(): কতটি রেকর্ড রিটার্ন হবে তা নির্ধারণ করে।
উদাহরণ: Pagination
ধরা যাক, আপনার একটি User টেবিল আছে এবং আপনি প্রথম পেজে ১০টি ব্যবহারকারী রিটার্ন করতে চান, দ্বিতীয় পেজে ১০টি, এবং আরও পরবর্তী পেজে বাকি ব্যবহারকারীদের দেখাতে চান।
import { DataSource } from "typeorm";
import { User } from "./entity/User";
// ডেটাবেস সংযোগ
const AppDataSource = new DataSource({
type: "postgres",
host: "localhost",
port: 5432,
username: "postgres",
password: "yourpassword",
database: "testdb",
entities: [User],
synchronize: true,
logging: true,
});
AppDataSource.initialize()
.then(async () => {
console.log("Data Source has been initialized!");
// Page 1, 10 users per page
const page = 1;
const pageSize = 10;
const users = await AppDataSource.getRepository(User).find({
skip: (page - 1) * pageSize, // (1 - 1) * 10 = 0
take: pageSize, // Take 10 records
});
console.log(users);
})
.catch((error) => console.log(error));
এখানে, প্রথম পেজে 10 ইউজার রিটার্ন করা হবে। আপনি skip এবং take মেথড ব্যবহার করে সহজেই pagination সেটআপ করতে পারেন।
TypeORM এ Sorting
Sorting হল ডেটাকে এক বা একাধিক কন্ডিশন বা কলামের ভিত্তিতে সাজানো। TypeORM এ order অপশন ব্যবহার করে ডেটাকে সাজানো যায়।
উদাহরণ: Sorting
ধরা যাক, আপনি User টেবিলের সমস্ত ইউজারকে name এর ভিত্তিতে সাজাতে চান। আপনি order অপশন ব্যবহার করতে পারেন।
const users = await AppDataSource.getRepository(User).find({
order: {
name: "ASC", // ASC for ascending order, DESC for descending order
},
});
console.log(users);
এখানে, name কলাম অনুযায়ী ব্যবহারকারীদের নাম অ্যালফাবেটিক অর্ডারে সাজানো হবে।
একাধিক কলাম দ্বারা Sorting
আপনি একাধিক কলামের ভিত্তিতেও sorting করতে পারেন। যেমন, প্রথমে name এবং পরে age এর ভিত্তিতে সাজানো।
const users = await AppDataSource.getRepository(User).find({
order: {
name: "ASC", // নামের ভিত্তিতে ascending
age: "DESC", // বয়সের ভিত্তিতে descending
},
});
console.log(users);
এখানে, name এর উপর প্রথমে ascending অর্ডারে সাজানো হবে, এবং তারপর age এর উপর descending অর্ডারে সাজানো হবে।
Pagination এবং Sorting একসাথে ব্যবহার করা
আপনি একসাথে pagination এবং sorting ব্যবহার করে একটি একক কুয়েরি তৈরি করতে পারেন, যেখানে ডেটাকে পেজিনেট এবং নির্দিষ্ট কলামের ভিত্তিতে সাজানো হবে।
উদাহরণ: Pagination এবং Sorting একসাথে
const page = 1;
const pageSize = 10;
const users = await AppDataSource.getRepository(User).find({
skip: (page - 1) * pageSize, // Pagination
take: pageSize, // Pagination
order: {
name: "ASC", // Sorting
},
});
console.log(users);
এখানে, প্রথমে pageSize এর সংখ্যা (১০) ব্যবহার করে pagination তৈরি করা হয়েছে এবং তারপর name কলামের ভিত্তিতে ascending অর্ডারে সাজানো হয়েছে।
সারাংশ
Pagination এবং Sorting হল TypeORM-এ ডেটাবেস ডেটার অপটিমাইজেশন এবং সহজ প্রদর্শন এর দুটি গুরুত্বপূর্ণ কৌশল। Pagination ব্যবহার করে আপনি ডেটাকে পেজে ভাগ করতে পারেন এবং Sorting ব্যবহার করে ডেটাকে নির্দিষ্ট কলাম অনুযায়ী সাজাতে পারেন। TypeORM এ skip(), take() এবং order অপশন ব্যবহার করে এগুলি খুব সহজে প্রয়োগ করা যায়, যা পারফরম্যান্স উন্নত করতে সহায়তা করে এবং ডেটার প্রদর্শন আরও কার্যকরী হয়।
Read more