বাংলা আর্টিকেল:Learn MERN Stack By Create Real-Estate Project -Part_3

বাংলা আর্টিকেল:Learn MERN Stack By Create Real-Estate Project -Part_3

(Learn Prisma & CRUD) ->Create a Real-estate Management Full-Stack Project To Learn React, NodeJs, MongoDB, Prisma And More Web Tools.

এই আর্টিকেল ,আমরা এক্সপ্লোর করব ডাটাবেস এর কোর রিলেশনশিপ , তিনটা মেইন ফান্ডামেন্টাল relationships : one-to-one, one-to-many, এবং many-to-many ।

আমরা user এবং Profile মডেল ডিফাইন ও তাদের ফিল্ড গুলির মধ্যে সম্পর্ক তৈরির মাধ্যমে বোঝার চেষ্টা করব prisma তে রিলেসন গুলি কেমন হয় এবং এর মাধ্যমে ডাটাবেস এ ডাটা স্টোর ও ইনসার্ট করে ।

#Let's break down each relationship type:

  1. One-to-One Relationship: এই টাইপের রিলেশনশিপ একটা কালেকশন এর সাথে অন্য একটা কালেকশন এর রিলেসন তৈরী করে। যেমন ধর user এর unique key এর সাথে Profile এর unique key এর connection তৈরী করবে।

  2. One-to-Many Relationship: একটি কালেকশন বা টেবিলের একটি field অন্য কালেকশন বা টেবিলের একাধিক ফিল্ডের সাথে connect হতে পারে। উদাহরণস্বরূপ, একটি User একটি Single Post তৈরি করতে পারে,আবার একই User একাধিক Post তৈরি করতে পারে।

    এর মানে দাঁড়ায়,একটি Post মডেল এ মাল্টিপল পোস্ট থাকতে পারে যা একজন সিঙ্গেল ইউসার create করে । এই ধরণের রিলেশনশিপ তখন প্রয়োজন হয় , যখন একজন User কালেকশন এর ইনস্ট্যান্স এর সাথে Post কালেকশন এর মাল্টিপল ইনস্ট্যান্স কানেক্ট করে।

  3. Many-to-Many Relationship: একটি কালেকশন এর মাল্টিপল record এর সাথে অন্ন্য একটা কালেকশন বা টেবিলের মাল্টিপল রেকর্ড এর সাথে রিলেসন ঘটতে পারে। উদহারণ দেয়া যায় : স্টুডেন্ট ও অনেক গুলো কোর্স মডেল তৈরী করা। একজন স্টুডেন্ট অনেকগুলি কোর্স enrolled করতে পারে,এবং একটি কোর্স অনেক স্টুডেন্ট একই সময় নিতে পারে ।

#Prisma and MongoDB offer distinct approaches to handle these relationships:

  • Prisma: Prisma একটি ORM (Object-Relational Mapping) tool যা ডাটাবেস ইন্ট্রিগ্রেশন সহজ করে । এটি মূলত স্কিমা ল্যাংগুজ এর মাধ্যমে ডাটাবেস এ টেবিল বা কালেকশন গুলির মধ্যে রিলেশন তৈরী করা ও তা ম্যানেজ করা allow করে। For instance, তুমি one-to-many relationship ঘটাতে পারো 'User' model এবং 'Post' model এর মধ্যে by utilizing the @relation attribute without ডিরেক্টলি ডাটাবেস এ হাত না দিয়ে । prisma তার স্কিমা মডেল এর সাহায্যে আমাদের এই সুবিধা দিয়ে থাকে .

  • MongoDB: MongoDB হল NoSQLডাটাবেস যা flexible document structure ফলো করে । MongoDB ডাটাবেস এ তুমি রেফারেন্স ব্যবহার করার মাধ্যমে রিলেসন ইমপ্লিমেন্ট করতে পার অথবা embedded document এসপেক্ট ফলো করতে পার। one-to-many এর উদহারণ যদি দেখি, তুমি user's posts array তে store করতে পার, within the user document । আর many-to-many এর জন্ন্য, array এর references ব্যবহার করা যায় রিলেসন তৈরির জন্য ।

আমরা প্রত্যেক relation এর একটি করে Model ও CRUD করব । এতেকরে, আরো ক্লিয়ার হবে।

The sample schema as an entity relationship diagram

উপরের ডায়াগ্রাম খেয়াল করলে দেখবে ,সবগুল রিলেসন এর কানেকশন পিকচার :

যেমন ধর , User এর একটা Profile থাকবে। প্ৰত্যেক ইউজারের জন্য একটা প্রোফাইল থাকবে এবং প্রত্যেক প্রোফাইলের একজন ইউজার থাকবে । আমরা একে One-to-one-relation বলবো।

একজন User অনেক গুলো Post থাকতে পারে ।যেহেতু user একজন এবং প্রত্যেক ইউসার অনেক গুলো পোস্ট করতে পারে তাই আমরা post এর উপর ভিত্তি করে একে one-to-many-relation এর আন্ডার এ ফেলতে পারি।

মনে কর ,মাল্টিপল post আছে , এবং প্রত্যেক পোস্ট এর জন্য মাল্টিপল ক্যাটেগরি আছে । Additionally, multiple posts একই সাথে গ্রুপ হতে পারে multiple categorie র সাথে। আমরা এমন রিলেসন কে many-to-many relationship বলতে পারি।

তবে,এই রিলেসন কনসেপ্ট বোঝা জরুরি, কারণ তুমি ডাটাবেস এ ডাটা কিভাবে অর্গানাইজ করে রাখবা ও একটার সাথে অন্য কালেকশন/টেবিল এর সম্পর্ক তৈরীর ফান্ডামেন্টার ক্লিয়ার হবে । বেটার কোয়েরি পারফর্মেন্স পাওয়ার জন্য এবং ডাটাবেস ডিসাইন এর রিয়েল ওয়ার্ল্ড ফীল পাবে এর মাধ্যমে।

তাই ধর্য্য ধরে পড়ার রেকোমেন্ডেশন ও রিকোয়েস্ট করছি । তুমি যদি one-to-one, one-to-many, এবং many-to-many relationships কনসেপ্ট বুজতে পার তবে ORM দিয়ে, যে কোন ডাটাবেস ডিজাইন সহজ হয়ে যাবে (Not এন্টারপ্রাইস লেবেল)। তাতে তুমি mongodb ব্যবহার কর বা অন্য যে কোন ডাটাবেস সিস্টেম।

Hey Script_Slingers,

Learn MERN Stack By Create Real-Estate Project এর পার্ট ৩ এ তোমায় স্বাগতম জানাচ্ছি। তুমি যদি আগের ২টা চ্যাপ্টার পড়ে না থাকো ,তবে এই পোস্ট এর নিচে প্রজেক্ট সিরিজ এর লিংক পেয়ে যাবে। যেখান থেকে দেখে আসতে পার কি কি এখন পর্যন্ত কমপ্লিট হয়েছে।

যেহেতু এটি একটি কমপ্লিট ফুলস্ট্যাক প্রজেক্ট সিরিজ তাই ধর্য্য ধরে সময় নিয়ে শেষ করার আহব্বান করছি। আমি তোমায় গ্যারান্টি দিচ্ছি শুধু প্রজেক্ট ই নয় ,তুমি এই প্রজেক্ট দিয়ে স্ক্র্যাচ থেকে ফুলস্ট্যাক ডেভেলপমেন্ট ফ্লো বুজতে পারবে। কনসেপ্ট ক্লিয়ার হবে এবং বিভিন্ন টুলস সম্পর্কে ,যেমন prisma ,React ,Express,CRUD এসব জানতে পারবে।

আমরা, এখন পর্যন্ত জেনেছি ,

  • ব্যাকএন্ড প্রজেক্ট সেটআপ।

  • প্যাকেজ ব্যবহার।

  • Prisma ও MongoDB কি, কেন এর ব্যবহার।

আরো অনেক ইনিশিয়াল স্টেজসেটিং -------------

আজকে আমরা Prisma মডেল ও ডাটাবেস এর most এসেন্সিয়াল কনসেপ্ট রিলেসন নিয়ে আগাচ্ছি।

এবং তোমার জন্য আজকে থাকছে prisma দিয়ে one-to-one-relation মডেল তৈরী করা ডাটাবেস এ তা push করা ও একটা ছোট্ট crud অপারেশন। বেসড on one-to-one রিলেশন ।

আসো শুরুকরি :

#One-to-One Relationship:

নিচের এক্সাম্পল এ একটি Prisma মডেল এক্সাম্পল দিয়েছি। তুমি ভালো করে খেয়াল কর। দেখতে পাবে আমাদের দুইটি মডেল আছে : User এবং Profile যা one-to-One রিলেশন মেইনটেইন করে ,যেখানে প্রতিটি User এর একটি এসোসিয়েট Profile থাকতে পারে, এবং প্রতিটি Profile এর সিঙ্গেল User সাথে connected আছে ।

Example-Model :

model User {
  id      String   @id @default(auto()) @map("_id") @db.ObjectId
  email   String   @unique @db.ObjectId
  profile Profile?
}

model Profile {
  id        String @id @default(auto()) @map("_id") @db.ObjectId
  name      String
  user      User   @relation(fields: [userEmail], references: [email])
  userEmail String @unique @db.ObjectId
}

বোঝার চেষ্টাকরি কি হচ্ছে :

User Model:

User মডেল আমাদের database এ user entity / collection represent করে । আমরা দুইটা মডেলকে এট্রিবিউট ও ফিল্ড ডিফাইন করার মাধ্যমে রিলেসন হ্যান্ডেল করেছি ।

এট্রিবিউট ও ফিল্ড এর বিবরণ দেখা যাক :

  • id: অবশ্যই আমাদের প্রত্যেক ইউসার এর একটা id থাকবে যা ,একটা কালেকশন এ প্রত্যেকটি ডকুমেন্ট কে আলাদা করবে। আমরা এর টাইপ বলে দিয়েছি String এবং @default(auto()) এট্রিবিউট এর মাধ্যমে ensure করে MongoDB ObjectId অটোমেটিক জেনারেট করবে। ObjectId mongodb তার underlilain সিস্টেম এর মাধ্যমে এই প্রসেস হ্যান্ডেল করে, যখনি নতুন ডকুমেন্ট ইনসার্ট হয় কালেকশন এ। এরপর @map("_id") ব্যবহার করেছি। prisma ফিল্ড map করতে । এর মধ্যে থাকা _id actually MongoDB document field ব্যবহার করে।

  • email: আমাদের User এর ইমেইল থাকবে। এবং @unique attribute এর মাধ্যমে আমরা , ensure করব একজন User এর জন্য অমুক ইমেইল Profile বরাদ্দ। ইমেইল ফিল্ড primery key হিসেবে ব্যবহার করব Profile model এর সাথে রিলেসন ঘটাতে। এবং এখানে @unique এট্রিবিউট must থাকতে হবে । কারণ আমরা এর উপর ভিত্তি করেই প্রত্যেক user কে আলাদা করব ডাটাবেস এ ।

  • profile : profile ফিল্ড এখানে Profile model এর সাথে one-to-one relationship তৈরী করে । আর ? এর মানে দাঁড়ায় ,ইউসার এর প্রোফাইল থাকতেও পারে আবার নাও থাকতে পারে,এটা অপশনাল। একজন user প্রথমে তার user ডকুমেন্ট তৈরী করবে এরপরে সে চাইলে প্রোফাইল এডজাস্ট করতে পারে।

Profile Model:

Profile মডেল ডাটাবেস এ profile entity বা কালেকশন represent করে । এখানে একটু ভালোকরে নজর দাও । কারণ মূল রিলেসন বিল্ড হচ্ছে এই মডেল এ ।

এট্রিবিউট ও ফিল্ড গুলির বর্ণনা :

model Profile {
  id        String @id @default(auto()) @map("_id") @db.ObjectId
  name      String
  user      User   @relation(fields: [userEmail], references: [email])
  userEmail String @unique @db.ObjectId
}
  • id: এই ক্ষেত্রেও একইভাবে একটা id থাকবে যা mongodb ObjectId ব্যবহার করে তৈরী হবে।

  • name: এই ফিল্ড এ ইউসার এর নাম নিব যার টাইপ স্ট্রিং।

  • user: user ফিল্ড User model এর সাথে one-to-one relationship স্টাব্লিস্ট করে । এটি স্পেসিফিকলি টারগেট করে একজন user এর profile কালেকশন এর সাথে রিলেসন আছে। @relation attribute ব্যবহার হয়েছে ,এটি নিদৃষ্ট করতে যে ,কোন field এর উপর ডিপেন্ড করে কানেক্ট হবে । @relation এর মধ্যে fields parameter এ [userEmail] হচ্ছে সেই কানেক্শন ব্রিজ আমাদের বর্তমান model এ । অন্যদিকে, references parameter [email] পয়েন্ট করে User model যা User মডেল এর প্রাইমারি key ।

  • userEmail: খেয়াল করলে দেখবে userEmail field এখানে foreign key রিপ্রেসেন্ট করে যা User model এর সাথে one-to-one relationship তৈরিতে ব্রিজ এর মত কাজ করছে । প্রত্যেক profile এর সাথে তার corresponding user লিংক ঘটায় । আর @unique attribute ensure করে প্রত্যেক টা ভ্যালু যেন আলাদা হয় এবং রেপিটেড না হয় collection এ ।

prisma মডেল তোমার ডাটাবেস এর একটাস্ট্রাকচার প্রোভাইড করে। একটা কালেকশন এর সাথে অন্য কালেকশন এর One-to-one লিংক তৈরী করে attributes এর মাধ্যমে , foreign keys গুলি data ইন্ট্রিগেট করে ইউনিক কিছু আইডেন্টিফায়ার এর মাধ্যমে ।

#Push The Model In MongoDB Database:

এবারে ,তুমি mongodb ডাটাবেস এ গেলে দেখতে পাবে আমাদের মেনুয়াললি create করা ডাটাবেস আছে prisma-crud নামে যা দেখতে নিচের ছবির মত :

ফিগার ১:

manual Database

তুমি যদি টার্মিনাল এ নিচের কমান্ডটি রান কর তবে স্কিমা বা মডেল অনুযায়ী MongDB তে ডাটাবেস কালেকশন তৈরী হয়ে যাবে :

//8:~/Documents/prisma-crud/server$ 
npx prisma db push

কমান্ড টি Prisma ORM এর মাধ্যমে কোড বেস থেকে স্কিমা সরাসরি কালেকশন push করে ডাটাবেস এ।

নিচের ইমেজ এ দেখো :

ফিগার ২:

আমাদের স্কিমা অনুযায়ী prisma-crud ডাটাবেস এ Profile এবং User কালেকশন তৈরী হয়েছে।

আমরা এবারে prisma ক্লায়েন্ট এর মাধ্যমে Rest api কোয়েরি ফলো করে crud অপারেশন চালাতে প্রস্তুত।

#One-to-One Crud:

ok তো ,তুমি অবশ্যই জান ,CRUD মানে create ,read ,update ,delete । এই প্ৰত্যেকটা অপারেশন মূলত ব্যবহার হয় ডাটাবেস এ ডাটা save করা, সেখান থেকে ডাটা read করা ,এক্সিস্টিং ডাটা delete করা ও স্পেসিফিক ডাটা update করার জন্য।

আমাদের ডাটাবেস অলরেডি সেট করা হয়েগেছে ।

crud অপারেশন গুলো চালানোর জন্য express আমাদের অনেক গুলো মেথড provide করে। এবং সেই সাথে prisma আমাদের কিছু কোয়েরি provide করে PrismaClient এর মাধ্যমে। যার সাহায্যে একটা ফুল crud প্রজেক্ট আমরা তৈরী করতে পারি। according আমাদের স্কিমা মডেল ।

Note : আমরা PrismaClient সম্পর্কে আগেই আলোচনা করেছি।

Express মেথড গুলোর মধ্যে : POST( ডাটা Create ) ,GET(ডাটা Read ) ,DELETE(সিঙ্গেল ডাটা Delete ),PUT(সিঙ্গেল ডাটা Update ) করার জন্য ব্যবহার হয়।

এছাড়া আরো অনেক মেথড আছে তবে, আপাতত আমাদের কাজ এই চারটা দিয়ে হয়ে যাবে।

Node : আমরা এই চ্যাপ্টার এ crud এর ডিটেলস ব্যাখ্যা করবো না। তোমার টাস্ক থাকবে কোড গুলোকে দেখে। একটু নিজের মত হাত নোংরা করা।
পরবর্তী চ্যাপ্টার এ crud এর ডিপ ইম্প্লিমেন্টেশন নিয়ে ডিটেলস আলোচনা করব।

এছাড়া ,আমরা index.js ফাইল এ সব কোড করছি , যা অর্গানিজ না। তাই পরবর্তী চ্যাপ্টার এ এগুলোকেও রেফেক্টের করব।

কারণ, তোমার অবশ্যই মনে আছে , reusable প্রিন্সিপল। কোড অর্গানাইজেশন ।

#first thing first:

প্রথমেই আমাদের ইনডেক্স ফাইল এ অন্য সব প্রয়োজনীয় প্যাকেজের সাথে PrismaClient ইম্পোর্ট করে নিচ্ছি ও একটা ইন্সটান্স তৈরী করছি :

//index.js
import express, { json } from "express";
import dotenv from "dotenv";
import cors from "cors";
import cookieParser from "cookie-parser";
import { PrismaClient } from "@prisma/client";
dotenv.config();
const app = express();
const prisma = new PrismaClient();
const PORT = process.env.PORT || 3000;

app.use(express.json());
app.use(cookieParser());
app.use(cors());

app.listen(PORT, () => {
  try {
    console.log(`Server is running on ${PORT}`);
  } catch (err) {
    console.log(err);
  }
});

import { PrismaClient } from "@prisma/client" এবং prisma ইনস্ট্যান্স create করতে, const prisma = new PrismaClient() এই লাইন দুইটি index.js এ অ্যাড করেছি।

আমরা প্রথমে কাজ করব get মেথড নিয়ে। যা, ডাটাবেস থেকে ডাটা read করার কাজ করে :

  • Get Data From User:

//index.js
//rest of the code ...
//GET ALL USER FROM DATABES
app.get("/api/users", async (req, res) => {
  try {
    const getAllUser = await prisma.user.findMany({
      include: {
        profile: true,
      },
    });
    if (getAllUser <= 0) {
      res.json({
        message: "No Data In Your Database",
      });
      return;
    }
    res.json(getAllUser);
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "Failed to retrieve users." });
  }
});
//rest of the code ...

এখানে জাস্ট get মেথড এর মধ্যে api এন্ডপয়েন্ট দিয়েছি ,একটা async কলব্যাক ফাঙ্কশন নিয়েছি যা,এক্সপ্রেস এর request ,response অবজেক্ট প্যারামিটার হিসেবে নিয়ে অপারেশন চালায়।

এরপর await prisma.user.findMany যা, prisma কোয়েরি তা ব্যবহার করে সব গুলো ডাটা user কালেকশন থেকে নিয়ে এসেছি।

💡
এগুলো ডিটেলস আলোচনা হবে next চ্যাপ্টার এ। তুমি জাস্ট এখন এক্সপ্লোর করো। তবে postman ,insomnia বা rest client দিয়ে কিভাবে api চেক করে, সেটা একটু Youtube থেকে দেখে নিও। সাথে বেসিক এক্সপ্রেস crud । তাহলে বুজতে সহজ হবে।
//অউটপুটঃ 
{
  "message": "No Data In Your Database"
}

কারণ আমাদের ডাটাবেস খালি।

next ,আমরা ডাটাবেস এ user তৈরী করার চেষ্টা করব with the help of এক্সপ্রেস post মেথড এবং prisma create কোয়েরি :

  • Create User:

//index.js
//rest of the code ...

// Create User and profile too.But Profile Is Optional

app.post("/api/users", async (req, res) => {
  try {
    const { email, profile } = req.body;
    const existingUser = await prisma.user.findUnique({
      where: {
        email: email,
      },
    });

    if (!existingUser) {
      const createNewUser = await prisma.user.create({
        data: {
          email,
          profile: {
            create: profile,
          },
        },
        include: {
          profile: true,
        },
      });
      res.json({
        message: "User Created",
        user: createNewUser,
      });
    } else {
      res.json({
        message: "User Already Existed",
        user: existingUser,
      });
    }
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "Failed to retrieve users." });
  }
});
//rest of the code ...

সেই আগের মতোই ,তবে এবারে Post মেথড ব্যবহার করেছে। এরপর req.body থেকে ক্লায়েন্ড এর দেয়া ইমেইল ও প্রোফাইল ডিসট্রাক্টর করে নিয়ে নিচ্ছে।

existingUser ভ্যারিয়েবল এ findUnique কোয়েরি ব্যবহার করে চেক করছি আমাদের user কালেকশন এ এই user ইমেইল আছে কিনা।আমরা আমাদের মডেল email ইউনিক রেখেছি , তাই সেটা দিয়ে চেক করছি।

then কন্ডিশন এ বলছি যদি না থাকে , তবে await prisma.user.create কুয়েরি চালিয়ে ইউসার তৈরী কর। ইউসার কে same time প্রোফাইল create করার অপশন দিচ্ছি ,চাইলে দিতে পারে নাহয় null থাকবে।

এবং শেষে json আকারে রেস্পন্স ব্যাক দিচ্ছি। sucess হলে মেসেজ দিবে User Created এবং ইউসার এর ডাটা দেখাবে । আর যদি user আগেই থাকে তবে else এ যাবে User Already Existed মেসেজ ডিসপ্লে করবে।

//আউটপুট 
{
  "message": "User Created",
  "user": {
    "id": "64eb79ee0f4f7e3b99e560f1",
    "email": "tmjishan2@gmail.com",
    "profile": {
      "id": "64eb79ef0f4f7e3b99e560f2",
      "name": "Tanvir Jishan",
      "userEmail": "tmjishan2@gmail.com"
    }
  }
}

Or 
{
  "message": "User Already Existed",
  "user": {
    "id": "64eb79ee0f4f7e3b99e560f1",
    "email": "tmjishan2@gmail.com"
  }
}

তুমি যদি চেষ্টা করো একই ইমেইল দিয়ে আবার রিকোয়েস্ট পাঠাতে তবে ২nd মেসেজ পাবে।

  • Delete User:

ডাটাবেস থেকে ডাটা ডিলিট করার জন্য express delete মেথড ও prisma delet কোয়েরি ব্যবহার করেছি :

//index.js
//rest of the code ...
// Delete Existing User By Email
app.delete("/api/users/:userEmail", async (req, res) => {
  try {
    const { userEmail } = req.params;
    const findProfile = await prisma.profile.findFirst({
      where: { userEmail: userEmail },
    });
    if (!findProfile) {
      res.json({
        message: "User And Profile Not In Databes",
        yourEmail: userEmail,
      });
    } else {
      await prisma.profile.delete({
        where: { userEmail: userEmail },
      });
      await prisma.user.delete({
        where: { email: userEmail },
      });
      res.json({
        message:"User and Associat Profile Deleted"
      })
    }
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "Failed to retrieve users." });
  }
});
//rest of the code ...

এখানে আমরা এন্ডপয়েন্ট এ req.params থেকে userEmail নিয়েছি , যা ক্লায়েন্ড দিচ্ছে। prisma.profile.findFirst কুয়েরি চালিয়ে চেক করছি profile কালেকশন এ userEmail আছে কিনা এবং একই সাথে findProfile ভ্যারিয়েবল এ স্টোর করেছি।

এরপর if এস্টেটমেন্ট এর মধ্যে চেক করছি যদি findProfile না থাকে তবে একটা মেসেজ দিবে "User And Profile Not In Databes" ,আর যদি থাকে তবে প্রথমে প্রোফাইল ডিলিট করবে according to userEmail এবং এর পরের লাইন এ ইউসার ডিলিট করে দিবে ইমেইল এর সাথে ম্যাচ করে। sucessfull হলে message:"User and Associat Profile Deleted"

এভাবে query চালানোর করার কারণ হচ্ছে ,profile এবং user একে অন্যের পরিপূরক। ডিলিট করার আরো ভালো সল্যুশন আছে ,তবে তা আমরা পরে এক্সপ্লোর করব ।

//আউটপুট :
{
  "message": "User and Associat Profile Deleted",
}
Or 
{
  "message": "User And Profile Not In Databes",
  "yourEmail": "tmjishan2@gmail.com"
}
  • Update User Emai :

একজন user এর ইমেইল এর উপর ভিত্তি করে আমরা তার এক্সিস্টিং ইমেইল কে এক্সপ্রেসের put ও prisma এর update কোয়েরি ব্যবহার করে চেঞ্জ করতে পারি ।

//index.js
//rest of the code ...
// Update User Data
app.put("/api/users/:userEmail", async (req, res) => {
  try {
    const { userEmail } = req.params;
    const { email } = req.body;
    const updatedUser = await prisma.user.update({
      where: { email: userEmail },
      data: { email },
    });
    res.json(updatedUser);

  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "Failed to update user." });
  }
});

//rest of the code ...

ঠিক ডিলিটের মতো আমরা req.params থেকে userEmail নিয়ে নিব এবং at the same time ক্লায়েন্ট কি নতুন ইমেইল আমাদের দিচ্ছে body তে ,তা req.body অবজেক্ট ডিস্ট্রাকচার থেকে নিয়ে পেয়ে যাব ।

এরপর কাজ সহজ , prisma await prisma.user.update কোয়েরি চালিয়ে চেক করব user কালেকশন এর ইমেইল আর userEmail এক কিনা। এক হলে data অবজেক্ট email এর জায়গায় body থেকে পাওয়া ইমেইল আপডেট করে দিব। আর রেস্পন্স আকারে যা আপডেট হয়েছে তা ক্লায়েন্ট কে শো করব।

এখানে তুমি দেখবা User ইমেইল আপডেট হওয়ার সাথে সাথে Profile userEmail আপডেট হয়ে গেছে। এটা শুধু রিলেসন এর জন্যই সম্ভব।

💡
SO, We done it well. Hope its make sense to you.If Yes ,then Lv A comment Bellow.

#Conclution:

নিচের কোড বেস এ সম্পূর্ণ ইনডেক্স ফাইল পাবে তুমি :

// complete index.js
import express, { json } from "express";
import dotenv from "dotenv";
import cors from "cors";
import cookieParser from "cookie-parser";
import { PrismaClient } from "@prisma/client";
import { userRouter } from "./routes/userRoute.js";

dotenv.config();
const app = express();
const prisma = new PrismaClient();
const PORT = process.env.PORT || 3000;

app.use(express.json());
app.use(cookieParser());
app.use(cors());

//GET ALL USER FROM DATABES

app.get("/api/users", async (req, res) => {
  try {
    const getAllUser = await prisma.user.findMany({
      include: {
        profile: true,
      },
    });
    if (getAllUser <= 0) {
      res.json({
        message: "No Data In Your Database",
      });
      return;
    }
    res.json(getAllUser);
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "Failed to retrieve users." });
  }
});

// Create User and profile too.But Profile Is Optional

app.post("/api/users", async (req, res) => {
  try {
    const { email, profile } = req.body;
    const existingUser = await prisma.user.findUnique({
      where: {
        email: email,
      },
    });

    if (!existingUser) {
      const createNewUser = await prisma.user.create({
        data: {
          email,
          profile: {
            create: profile,
          },
        },
        include: {
          profile: true,
        },
      });
      res.json({
        message: "User Created",
        user: createNewUser,
      });
    } else {
      res.json({
        message: "User Already Existed",
        user: existingUser,
      });
    }
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "Failed to retrieve users." });
  }
});

// Delete Existing User By Email
app.delete("/api/users/:userEmail", async (req, res) => {
  try {
    const { userEmail } = req.params;
    const findProfile = await prisma.profile.findFirst({
      where: { userEmail: userEmail },
    });
    if (!findProfile) {
      res.json({
        message: "User And Profile Not In Databes",
        yourEmail: userEmail,
      });
    } else {
      await prisma.profile.delete({
        where: { userEmail: userEmail },
      });
      await prisma.user.delete({
        where: { email: userEmail },
      });
      res.json({
        message: "User and Associat Profile Deleted",
      });
    }
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "Failed to retrieve users." });
  }
});

// Update User Data

app.put("/api/users/:userEmail", async (req, res) => {
  try {
    const { userEmail } = req.params;
    const { email } = req.body;
    const updatedUser = await prisma.user.update({
      where: { email: userEmail },
      data: { email },
    });
    res.json(updatedUser);

  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "Failed to update user." });
  }
});

app.listen(PORT, () => {
  try {
    console.log(`Server is running on ${PORT}`);
  } catch (err) {
    console.log(err);
  }
});

তুমি দেখে প্রাকটিস করতে থাকো, আশাকরি এর পরে prisma one-to-one আর crud নিয়ে কোন সমস্যা থাকবে না।
আর তা ছাড়া এখনো ২ তা রিলেসন আছে ,যা দেখলে আশাকরা যায় crud and prisma পানির মতো সহজ হবে।

Note: ব্যাকএন্ড একটা থিওরি হাউস ,এর কনসেপ্ট বুজতে বুজতেই সময় লাগে বেশি।

তাই ধার্য ধরে আগাতে থাকলে একটা সময় এই জিনিস গুলি সহজ হবে। এছাড়া মোটাদাগে বলাযায় ব্যাকএন্ড এ ,এগুলো রেপিটিটিভ কাজ। প্রায় সব এপ্লিকেশন এ crud ,ডাটাবেস মেনেজমেন্ট লাগে ।even ডিফ্রেন্ট প্রোগ্রামিং ল্যাঙ্গুয়েজেও same । তাই বিষয় গুলো আয়ত্তে থাকতে হবে।

পরবর্তী চ্যাপ্টার এ card ইম্প্লিমেন্টেশন ,prisma কোয়েরি ডিটেলস আলোচনা করার চেষ্টা করব।

💡
তোমার feedback আশাকরছি । লেখা সম্পর্কে যে কোন মন্তব্য করতে পার ভাল কিংবা খারাপ। এতে করে লেখার মোটিভেশন বেড়ে যায়।

আজকের জন্য ------- Bদায় .......

#devTj #tanvir_mehedi #Prisma #mernstack #javascript