Super Kawaii Cute Cat Kaoani
๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
{Extracurricular Activities}/Codeit Boost-Node.js

6์ฃผ์ฐจ ์Šคํ„ฐ๋”” ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ํ™œ์šฉํ•œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์„œ๋ฒ„ ๋งŒ๋“ค๊ธฐ(1) [์ฝ”๋“œ์ž‡ ๋ถ€์ŠคํŠธ ๋ฐฑ์—”๋“œ ์Šคํ„ฐ๋””]

by wonee1 2024. 7. 3.
๋ฐ˜์‘ํ˜•

 

 

<๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ํ™œ์šฉํ•œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์„œ๋ฒ„ ๋งŒ๋“ค๊ธฐ>

 

 

 

 

๐Ÿ’ก์ €์žฅํ•˜๋ ค๋Š” ๋ฐ์ดํ„ฐ์˜ ๋ช…ํ™•ํ•œ ๊ตฌ์กฐ๊ฐ€ ์žˆ๊ณ  ๋ฐ์ดํ„ฐ ๊ฐ„์˜ ๊ด€๊ณ„๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ ์žˆ์„ ๋•Œ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์ฃผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค

 

 

DBMS(Database Management System)

 

 

 

javascript์˜ ORM ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ์†Œํ†ตํ•  ์ˆ˜ ์žˆ๊ณ  ๊ฐ์ฒด์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค

 


 

Prisma ๊ธฐ๋ณธ๊ธฐ

Prisma ์ดˆ๊ธฐํ™”

 

prisma๋Š” npx๋กœ ์‹œ์ž‘ํ•œ๋‹ค

→ npx prisma init -- datasource-provider postgresql

 

 

.env๋Š” postgreSQL์— ์ ‘์†ํ•˜๊ธฐ ์œ„ํ•œ ํ™˜๊ฒฝ๋ณ€์ˆ˜ ํŒŒ์ผ

 

ํ•„์š”ํ•œ ํ…Œ์ด๋ธ”๊ตฌ์กฐ๋ฅผ ์ •์˜ํ•˜๋Š” ํŒŒ์ผ

 

 

User ๋ชจ๋ธ ๋งŒ๋“ค๊ธฐ 

 

 

model์ด๋ž€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”์„ ๋‚˜ํƒ€๋‚ธ๋‹ค

ํ•„๋“œ ์ด๋ฆ„ ํ•„ํŠธ ํƒ€์ž…์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค

model User {
  id        String @id @default(uuid()) //uuid๋Š” 36์ž๋กœ ์ด๋ฃจ์–ด์ง„ idํ˜•์‹
  email     String @unique
  firstName String
  lastName  String
  address   String
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

• model์€ ์ ์–ด๋„ ํ•˜๋‚˜์˜ ์œ ๋‹ˆํฌ ํ•„๋“œ๊ฐ€ ํ•„์š”ํ•˜๋‹ค

• @ ๋กœ ํ•„๋“œ์˜ ์ถ”๊ฐ€์ •๋ณด๋ฅผ ๋ช…์‹œํ•œ๋‹ค

 

 

 

Prisma Schema ์ถ”๊ฐ€ ๊ธฐ๋Šฅ

 

 

enum

 

•ํ•„๋“œ์˜ ๊ฐ’์ด ๋ช‡ ๊ฐ€์ง€ ์ •ํ•ด์ง„ ๊ฐ’ ์ค‘ ํ•˜๋‚˜์ผ ๋•Œ๋Š” enum(enumerated type)์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

model User {
  // ...
  membership  Membership  @default(BASIC)
}

enum Membership {
  BASIC
  PREMIUM
}

• enum ๊ฐ’์€ ๋ณดํ†ต ๋Œ€๋ฌธ์ž๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ํ•„๋“œ์˜ ํƒ€์ž…์„ enum ์ด๋ฆ„์œผ๋กœ ์„ค์ •ํ•˜๋ฉด ๋œ๋‹ค.

•@default ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

• enum์€ ์„œ๋กœ ์—ฐ๊ด€๋œ ์ƒ์ˆ˜๋“ค์˜ ์ง‘ํ•ฉ

• SQLite์—์„œ๋Š” enum์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค

 

 

 

 

@@unique

 

•์—ฌ๋Ÿฌ ํ•„๋“œ์˜ ์กฐํ•ฉ์ด uniqueํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ @@unique ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

•@@unique ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๋Š” ํŠน์ • ํ•„๋“œ์— ์ข…์†๋œ ์–ดํŠธ๋ฆฌ๋ทฐํŠธ๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ชจ๋ธ ์•„๋ž˜ ๋ถ€๋ถ„์— ์“ด๋‹ค.

 

model User {
  id        String   @id @default(uuid())
  email     String   @unique
  firstName String
  lastName  String
  address   String
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  @@unique([firstName, lastName])
}

 

•์œ„์ฒ˜๋Ÿผ ์ •์˜ํ•˜๋ฉด firstName๊ณผ lastName์˜ ์กฐํ•ฉ์ด uniqueํ•ด์•ผ ํ•œ๋‹ค.

 

// ์‚ฝ์ž… ๊ฐ€๋Šฅ

{
  id: "abc",
  firstName: "๊ธธ๋™",
  lastName: "ํ™",
  // ...
},
{
  id: "def",
  firstName: "๊ธธ๋™",
  lastName: "๋ฐ•",
  // ...
}

 

 

 

 

๋งˆ์ด๊ทธ๋ ˆ์ด์…˜

 

๐Ÿ’กmodel์ฝ”๋“œ๋ฅผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ฐ˜์˜ํ•˜๋Š” ๊ณผ์ •์„ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์ด๋ผ๊ณ  ํ•œ๋‹ค

→ npx prisma migrate dev ์œผ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜

 

 

schema prisma์— ์žˆ๋˜ ์ฝ”๋“œ๋ฅผ sql๋ฌธ์œผ๋กœ ๋ฐ”๊ฟ”์ค€๋‹ค

 

 

npx prisma studio๋กœ ์ ‘์†ํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ž…๋ ฅํ•œ๋‹ค

 

 

ํ…Œ์ด๋ธ”์— ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ์„ ๋•Œ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๊ธฐ

 

-- CreateEnum
CREATE TYPE "Category" AS ENUM ('FASHION', 'BEAUTY', 'SPORTS', 'ELECTRONICS', 'HOME_INTERIOR', 'HOUSEHOLD_SUPPLIES', 'KITCHENWARE');

-- AlterTable
ALTER TABLE "User" ADD COLUMN     "age" INTEGER;

-- CreateTable
CREATE TABLE "Product" (
    "id" TEXT NOT NULL,
    "name" TEXT NOT NULL,
    "description" TEXT,
    "category" "Category" NOT NULL,
    "price" DOUBLE PRECISION NOT NULL,
    "stock" INTEGER NOT NULL,
    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updatedAt" TIMESTAMP(3) NOT NULL,

    CONSTRAINT "Product_pkey" PRIMARY KEY ("id")
);

 

 

 

Product ํ…Œ์ด๋ธ” ๋งŒ๋“ค๊ธฐ

 

 

model Product {
  id          String   @id @default(uuid())
  name        String
  description String?
  category    Category
  price       Float
  stock       Int
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
}

enum Category {
  FASHION
  BEAUTY
  SPORTS
  ELECTRONICS
  HOME_INTERIOR
  HOUSEHOLD_SUPPLIES
  KITCHENWARE
}

 

 

 

 

Prisma Client์™€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค CRUD I

 

prisma client๋Š” ๋ชจ๋ธ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๊ณ  ์žˆ๋‹ค

 

 

client ์‚ฌ์šฉ๋ฒ•

import { PrismaClient } from '@prisma/client';//client๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ฝ”๋“œ 
...
...

app.get('/users', async (req, res) => {
    const users = await prisma.user.findMany(); //์–ด๋–ค ๋ชจ๋ธ๊ณผ ์ƒํ˜ธ์ž‘์šฉํ•˜๋ ค๋ฉด prisma.๋ชจ๋ธ์ด๋ฆ„
    //๋ชจ๋ธ์ด๋ฆ„์€ schema.prisma ํŒŒ์ผ์— ์ •์˜๋œ ๋ชจ๋ธ์˜ ์ด๋ฆ„์„ ์ฐธ์กฐ
    res.send(users);
});

app.get('/users/:id', async (req, res) => {
    const { id } = req.params;
    const user = await prisma.user.findUnique({//๊ณ ์œ ํ•„๋“œ๋กœ ๋ฐ์ดํ„ฐํ•˜๋‚˜๋ฅผ ์ฐพ์„ ๋•Œ findUnique ์‚ฌ์šฉ
        where: { id },//where๋กœ ๊ฒฐ๊ณผ๋ฅผ ํ•„ํ„ฐ
    });//id์— ํ•ด๋‹นํ•˜๋Š” ์œ ์ € ์กฐํšŒ
    res.send(user);
});

 

 

Prisma์—์„œ ๋ชจ๋ธ๊ณผ ์ƒํ˜ธ์ž‘์šฉํ•  ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ฃผ์š” ๋ฉ”์„œ๋“œ

  • findMany: ์—ฌ๋Ÿฌ ๋ ˆ์ฝ”๋“œ๋ฅผ ์กฐํšŒ
  • findUnique: ๊ณ ์œ ํ•œ ๋‹จ์ผ ๋ ˆ์ฝ”๋“œ๋ฅผ ์กฐํšŒ
  • create: ์ƒˆ๋กœ์šด ๋ ˆ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑ
  • update: ๊ธฐ์กด ๋ ˆ์ฝ”๋“œ๋ฅผ ์—…๋ฐ์ดํŠธ
  • delete: ๊ธฐ์กด ๋ ˆ์ฝ”๋“œ๋ฅผ ์‚ญ์ œ.
  • upsert: ๋ ˆ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ์—…๋ฐ์ดํŠธ
  • findFirst: ์ฒซ ๋ฒˆ์งธ ๋ ˆ์ฝ”๋“œ๋ฅผ ์กฐํšŒ
  • count: ํŠน์ • ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ๋ ˆ์ฝ”๋“œ์˜ ์ˆ˜๋ฅผ ์…ˆ

 

 

Prisma Client์™€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค CRUD II

 

app.post('/users', async (req, res) => {
  // ๋ฆฌํ€˜์ŠคํŠธ ๋ฐ”๋”” ๋‚ด์šฉ์œผ๋กœ ์œ ์ € ์ƒ์„ฑ-> create ๋ฉ”์†Œ๋“œ ์‚ฌ์šฉ
  const user = await prisma.user.create({
    data:req.body,

  });
  res.status(201).send(user);
});

app.patch('/users/:id', async (req, res) => {
  const { id } = req.params;
  // ๋ฆฌํ€˜์ŠคํŠธ ๋ฐ”๋”” ๋‚ด์šฉ์œผ๋กœ id์— ํ•ด๋‹นํ•˜๋Š” ์œ ์ € ์ˆ˜์ • ->update๋ฉ”์†Œ๋“œ ์‚ฌ์šฉ
  const user = await prisma.user.update({
    where: {id }, // where id๋ฅผ ๋„˜๊ฒจ์ค€๋‹ค
    data: req.body, //data๋กœ req.body๋ฅผ ๋„˜๊ฒจ์ค€๋‹ค
  });
  res.send(user);
});

app.delete('/users/:id', async (req, res) => {
  const { id } = req.params;
  // id์— ํ•ด๋‹นํ•˜๋Š” ์œ ์ € ์‚ญ์ œ
  await prisma.user.delete({
    where: {id},
  });

  res.sendStatus(204);
});

 

 

Product CRUD API ๋งŒ๋“ค๊ธฐ

 

import * as dotenv from 'dotenv';
dotenv.config();
import express from 'express';
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

const app = express();
app.use(express.json());

/*********** users ***********/

app.get('/users', async (req, res) => {
  const users = await prisma.user.findMany();
  res.send(users);
});

app.get('/users/:id', async (req, res) => {
  const { id } = req.params;
  const user = await prisma.user.findUnique({
    where: { id },
  });
  res.send(user);
});

app.post('/users', async (req, res) => {
  const user = await prisma.user.create({
    data: req.body,
  });
  res.status(201).send(user);
});

app.patch('/users/:id', async (req, res) => {
  const { id } = req.params;
  const user = await prisma.user.update({
    where: { id },
    data: req.body,
  });
  res.send(user);
});

app.delete('/users/:id', async (req, res) => {
  const { id } = req.params;
  await prisma.user.delete({
    where: { id },
  });
  res.sendStatus(204);
});

/*********** products ***********/

app.get('/products', async (req, res) => {
  const products = await prisma.product.findMany();
  res.send(products);
});

app.get('/products/:id', async (req, res) => {
  const { id } = req.params;
  const product = await prisma.product.findUnique({
    where: { id },
  });
  res.send(product);
});

app.post('/products', async (req, res) => {
  const product = await prisma.product.create({
    data: req.body,
  });
  res.status(201).send(product);
});

app.patch('/products/:id', async (req, res) => {
  const { id } = req.params;
  const product = await prisma.product.update({
    where: { id },
    data: req.body,
  });
  res.send(product);
});

app.delete('/products/:id', async (req, res) => {
  const { id } = req.params;
  await prisma.product.delete({
    where: { id },
  });
  res.sendStatus(204);
});

app.listen(process.env.PORT || 3000, () => console.log('Server Started'));

 

 

 

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์‹œ๋”ฉ

 

mock ๋ฐ์ดํ„ฐ๋ฅผ ์‹œ๋“œ ์ปค๋งจ๋“œ๋ฅผ ์‹คํ–‰ํ•ด์„œ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์— ์‹œ๋”ฉํ•œ๋‹ค

seed.js

import { PrismaClient } from '@prisma/client';
import {USERS} from './mock.js'

const prisma = new PrismaClient();

async function main() {
  // ๊ธฐ์กด ๋ฐ์ดํ„ฐ ์‚ญ์ œ
  await prisma.user.deleteMany();

  // ๋ชฉ ๋ฐ์ดํ„ฐ ์‚ฝ์ž…
  await prisma.user.createMany({
    data: USERS,
    skipDuplicates: true, // ์œ ๋‹ˆํฌํ•œ ํ•„๋“œ๊ฐ€ ์ค‘๋ณต๋˜๋Š” ๋ฐ์ดํ„ฐ๋“ค์€ ์Šคํ‚ต
  })
}

main() //mainํ•จ์ˆ˜๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ์‹คํ–‰ํ•˜๋Š” ์ฝ”๋“œ-> ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰ ๋œ ํ›„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€์˜ ์—ฐ๊ฒฐ์„ ์ข…๋ฃŒ
  .then(async () => {
    await prisma.$disconnect();
  })
  .catch(async (e) => {
    console.error(e);
    await prisma.$disconnect();
    process.exit(1);
  });

package.json ์ˆ˜์ •

{
  "dependencies": {
    "@prisma/client": "^5.4.2",
    "dotenv": "^16.3.1",
    "express": "^4.18.2",
    "is-email": "^1.0.2",
    "is-uuid": "^1.0.2",
    "prisma": "^5.4.2",
    "superstruct": "^1.0.3"
  },
  "devDependencies": {
    "nodemon": "^3.0.1"
  },
  "type": "module",
  "scripts": {
    "dev": "nodemon app.js",
    "start": "node app.js"
  },
  "prisma":{
    "seed":"node prisma/seed.js"
  }
}

npx prisma db seed ๋ช…๋ น์–ด๋กœ ์‹คํ–‰ํ•œ๋‹ค

๊ทธ ํ›„ prisma studio๋ฅผ ์‹คํ–‰์‹œํ‚จ๋‹ค

 

 

 

 

 

 

์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ ์ฒ˜๋ฆฌํ•˜๊ธฐ

 

 

offset์€ ๋ฐ์ดํ„ฐ ๋ช‡ ๊ฐœ๋ฅผ ๊ฑด๋„ˆ๋›ธ ๊ฒƒ์ธ์ง€ ๊ฒฐ์ •ํ•œ๋‹ค

limit๊ณผ offset์„ ๊ฒฐ๊ณผ๋ฅผ ํŽ˜์ด์ง€์ฒ˜๋Ÿผ ๋‚˜๋ˆ ์„œ ๊ฐ€์ ธ์˜ค๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋‹ค

app.get('/users', async (req, res) => {
    const {offset =0, limit=10, order ='newest'}=req.query;//๋””ํดํŠธ ๊ฐ’์„ ํ• ๋‹น
    let orderBy;
    switch (order) {
      case 'oldest':
        orderBy={createdAt:'asc'};
        break;
      case 'newest':
      default:
        orderBy={createdAt:'desc'}
        
    }
    
    const users = await prisma.user.findMany({
      //orderBy: {createdAt:'asc'},//์˜ค๋ฆ„์ฐจ์ˆœ ์ •๋ ฌ 
      orderBy,
      skip: parseInt(offset), //skip ํ”„๋กœํผํ‹ฐ๋กœ ์„ค์ •, ์ˆซ์ž๋กœ ํ• ๋‹น
      take: parseInt(limit), // take ํ”„๋กœํผํ‹ฐ๋กœ ์„ค์ •, ์ˆซ์ž๋กœ ํ• ๋‹น 
      
    }); //์–ด๋–ค ๋ชจ๋ธ๊ณผ ์ƒํ˜ธ์ž‘์šฉํ•˜๋ ค๋ฉด prisma.๋ชจ๋ธ์ด๋ฆ„
    ////๋ชจ๋ธ์ด๋ฆ„์€ schema.prisma ํŒŒ์ผ์— ์ •์˜๋œ ๋ชจ๋ธ์˜ ์ด๋ฆ„์„ ์ฐธ์กฐ

    res.send(users);
});

 

 

http

GET <http://localhost:3000/users?order=oldest>

 

 

 

Prisma Client ์ถ”๊ฐ€ ๊ธฐ๋Šฅ

 

 

์ถ”๊ฐ€์ ์ธ CRUD ๋ฉ”์†Œ๋“œ

 

.findFirst()

• id๋กœ ๊ฐ์ฒด ํ•˜๋‚˜๋ฅผ ์กฐํšŒํ•  ๋•Œ๋Š” .findUnique() ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ–ˆ์Œ.

•.findUnique() ๋ฉ”์†Œ๋“œ๋Š” id ํ•„๋“œ๋‚˜ uniqueํ•œ ํ•„๋“œ๋กœ๋งŒ ํ•„ํ„ฐ๋ฅผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// OK
const user = await prisma.user.findUnique({
  where: { id: 'b8f11e76-0a9e-4b3f-bccf-8d9b4fbf331e' },
});

// ์˜ค๋ฅ˜(firstName์€ uniqueํ•œ ํ•„๋“œ๊ฐ€ ์•„๋‹˜)
const user = await prisma.user.findUnique({
  where: { firstName: '๊ธธ๋™' },
});

๐Ÿ’กUniqueํ•˜์ง€ ์•Š์€ ํ•„๋“œ๋กœ ํ•„ํ„ฐ๋ฅผ ํ•ด์„œ ๊ฐ์ฒด ํ•˜๋‚˜๋ฅผ ์กฐํšŒํ•˜๊ณ  ์‹ถ์„ ๋•Œ๋Š” .findFirst() ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

const user = await prisma.user.findFirst({
  where: { firstName: '๊ธธ๋™' },
});

console.log(user);

{
  "id": "b8f11e76-0a9e-4b3f-bccf-8d9b4fbf331e",
  "email": "honggd@example.com",
  "firstName": "๊ธธ๋™",
  "lastName": "ํ™",
  "address": "์„œ์šธํŠน๋ณ„์‹œ ๊ฐ•๋‚จ๊ตฌ ๋ฌด์‹ค๋กœ 123๋ฒˆ๊ธธ 45-6",
  "createdAt": "2023-07-16T09:00:00.000Z",
  "updatedAt": "2023-07-16T09:00:00.000Z"
}

• where ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ๊ฒฐ๊ณผ๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ ์žˆ์„ ๋•Œ ์ฒซ ๋ฒˆ์งธ ๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ดํ•˜๋‹ค.

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ์ˆœ์„œ๋ฅผ ๋ฐ”๊พธ๊ณ  ์‹ถ๋‹ค๋ฉด orderBy ํ”„๋กœํผํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

 

 

.upsert()

•.upsert() ๋ฉ”์†Œ๋“œ๋Š” where ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ๊ฐ์ฒด๊ฐ€ ์žˆ๋‹ค๋ฉด ๊ฐ์ฒด๋ฅผ ์—…๋ฐ์ดํŠธ(update) ํ•˜๊ณ , ์—†๋‹ค๋ฉด ์ƒ์„ฑ(insert) ํ•œ๋‹ค( Update์™€ insert๋ฅผ ํ•ฉ์นœ ๋ฉ”์†Œ๋“œ)

const user = await prisma.user.upsert({
  where: { email: 'yjkim@example.com' },
  data: {
    email: 'yjkim@example.com',
    firstName: '์œ ์ง„',
    lastName: '๊น€',
    address: '์ถฉ์ฒญ๋ถ๋„ ์ฒญ์ฃผ์‹œ ๋ถ๋ฌธ๋กœ 210๋ฒˆ๊ธธ 5',
  },
});

 

 

.count()

• ๊ฐ์ฒด์˜ ๊ฐœ์ˆ˜๋งŒ ํ•„์š”ํ•œ ๊ฒฝ์šฐ .count() ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

• .findMany()๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฐฐ์—ด์˜ ๊ธธ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๋” ํšจ์œจ์ 

const count = await prisma.product.count({
  where: {
    category: 'FASHION',
  },
});

console.log(count);

16

 

 

ํ•„ํ„ฐ ์กฐ๊ฑด

•where ํ”„๋กœํผํ‹ฐ์— ํ•„๋“œ ์ด๋ฆ„๊ณผ ๊ฐ’์„ ์ „๋‹ฌํ•˜๋ฉด ๊ธฐ๋ณธ์ ์œผ๋กœ ์ผ์น˜(equal) ์—ฐ์‚ฐ์ž๊ฐ€ ํ™œ์šฉ๋œ๋‹ค

// category๊ฐ€ 'FASHION'์ธ Product๋“ค ํ•„ํ„ฐ
const products = await prisma.product.findMany({
  where: {
    category: 'FASHION',
  },
});

์ด ์™ธ์—๋„ not, in, contains, startsWith ๊ฐ™์€ ๋‹ค์–‘ํ•œ ๋น„๊ต ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค

// category๊ฐ€ 'FASHION'์ด ์•„๋‹Œ Product๋“ค ํ•„ํ„ฐ
const products = await prisma.product.findMany({
  where: {
    category: {
      not: 'FASHION',
    },
  },
});

// category๊ฐ€ 'FASHION', 'SPORTS', 'BEAUTY' ์ค‘ ํ•˜๋‚˜์ธ Product๋“ค ํ•„ํ„ฐ
const products = await prisma.product.findMany({
  where: {
    category: {
      in: ['FASHION', 'SPORTS', 'BEAUTY']
    },
  },
});

// name์— 'TV'๊ฐ€ ๋“ค์–ด๊ฐ€๋Š” Product๋“ค ํ•„ํ„ฐ
const products = await prisma.product.findMany({
  where: {
    name: {
      contains: 'TV',
    },
  },
});

// name์ด 'Apple'๋กœ ์‹œ์ž‘ํ•˜๋Š” Product๋“ค ํ•„ํ„ฐ
const products = await prisma.product.findMany({
  where: {
    name: {
      startsWith: 'Apple',
    },
  },
});

๊ทธ๋ฆฌ๊ณ  ์—ฌ๋Ÿฌ ํ•„ํ„ฐ๋ฅผ ์กฐํ•ฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค

• AND(์—ฌ๋Ÿฌ ํ•„ํ„ฐ ์กฐ๊ฑด์„ ๋ชจ๋‘ ๋งŒ์กฑํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ): where ์•ˆ์— ํ”„๋กœํผํ‹ฐ๋ฅผ ์—ฌ๋Ÿฌ ๊ฐœ ์“ฐ๋ฉด ๋œ๋‹ค

// category๊ฐ€ 'FASHION'์ด๋ฉด์„œ name์— '๋‚˜์ดํ‚ค'๊ฐ€ ๋“ค์–ด๊ฐ€๋Š” Product๋“ค ํ•„ํ„ฐ
const products = await prisma.product.findMany({
  where: {
    category: 'FASHION',
    name: {
      contains: '๋‚˜์ดํ‚ค',
    },
  },
});

• OR(์—ฌ๋Ÿฌ ํ•„ํ„ฐ ์กฐ๊ฑด ์ค‘ ํ•˜๋‚˜๋งŒ ๋งŒ์กฑํ•ด๋„ ๋˜๋Š” ๊ฒฝ์šฐ): OR ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค

// name์— '์•„๋””๋‹ค์Šค'๊ฐ€ ๋“ค์–ด๊ฐ€๊ฑฐ๋‚˜ '๋‚˜์ดํ‚ค'๊ฐ€ ๋“ค์–ด๊ฐ€๊ฑฐ๋Š” Product๋“ค ํ•„ํ„ฐ
const products = await prisma.product.findMany({
  where: {
    OR: [
      {
        name: {
          contains: '์•„๋””๋‹ค์Šค',
        },
      },
      {
        name: {
          contains: '๋‚˜์ดํ‚ค',
        },
      },
    ],
  },
});

• NOT(ํ•„ํ„ฐ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋ฉด ์•ˆ ๋˜๋Š” ๊ฒฝ์šฐ): NOT ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค

// name์— '์‚ผ์„ฑ'์ด ๋“ค์–ด๊ฐ€์ง€๋งŒ 'TV'๋Š” ๋“ค์–ด๊ฐ€์ง€ ์•Š๋Š” Product๋“ค ํ•„ํ„ฐ
const products = await prisma.product.findMany({
  where: {
    name: {
      contains: '์‚ผ์„ฑ',
    },
    NOT: {
      name: {
        contains: 'TV',
      },
    },
  },
});

 

 

 

์œ ํšจ์„ฑ ๊ฒ€์‚ฌ

 

 

Superstruct Types ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ํ•œ๋‹ค

 

 

import * as s from 'superstruct';
import isEmail from 'is-email';

//์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋Š” ์ˆ˜ํผ์ŠคํŠธ๋ŸญํŠธ๋กœ ์˜ˆ์ƒํ•˜๋Š” ๋ฐ์ดํ„ฐ ํ˜•์‹์„ ์ •์˜ํ•˜๊ณ 
// ์‹ค์ œ ๋ฐ›์€ ๋ฐ์ดํ„ฐ๊ฐ€ ํ˜•์‹๊ณผ ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธ 

export const CreateUser= s.object({
    email:s.define('Email',isEmail),//emailํƒ€์ž…์€ isEmailํ˜•์‹์„ ํ†ต๊ณผํ•ด์•ผํ•œ๋‹ค
    firstName:s.size(string(),1,30),//size ํ•จ์ˆ˜๋Š” string ํƒ€์ž…์˜ ๊ธธ์ด๋ฅผ ์ œํ•œ 
    lastName:s.size(string(),1,30),
    address:s.string(),
});

export const PatchUser=s.partial(CreateUser);// CreateUser์˜ ์ผ๋ถ€๋ฉด ok

 

 

app.js ํŒŒ์ผ์„ ์ˆ˜์ •

import { assert } from 'superstruct';
import { CreateUser , PatchUser} from './struct';
app.post('/users', async (req, res) => {
  assert(req.body,CreateUser); // ํ™•์ธํ•˜๊ณ ์žํ•˜๋Š” ๋ฐ์ดํ„ฐ ๊ฐ์ฒด์™€ ์ˆ˜ํผ์ŠคํŠธ๋ŸญํŠธ ๊ฐ์ฒด๋ฅผ ์ „๋‹ฌํ•˜๋ฉด ๋œ๋‹ค (์œ ํšจ์„ฑ ๊ฒ€์‚ฌ)
  // ๋ฆฌํ€˜์ŠคํŠธ ๋ฐ”๋”” ๋‚ด์šฉ์œผ๋กœ ์œ ์ € ์ƒ์„ฑ-> create ๋ฉ”์†Œ๋“œ ์‚ฌ์šฉ
  const user = await prisma.user.create({
    data:req.body,

  });
  res.status(201).send(user);
});

app.patch('/users/:id', async (req, res) => {
  assert(req.body,PatchUser); 
  const { id } = req.params;
  // ๋ฆฌํ€˜์ŠคํŠธ ๋ฐ”๋”” ๋‚ด์šฉ์œผ๋กœ id์— ํ•ด๋‹นํ•˜๋Š” ์œ ์ € ์ˆ˜์ • ->update๋ฉ”์†Œ๋“œ ์‚ฌ์šฉ
  const user = await prisma.user.update({
    where: {id }, // where id๋ฅผ ๋„˜๊ฒจ์ค€๋‹ค
    data: req.body, //data๋กœ req.body๋ฅผ ๋„˜๊ฒจ์ค€๋‹ค
  });
  res.send(user);
});

 

 

๋ฐ˜์‘ํ˜•

'{Extracurricular Activities} > Codeit Boost-Node.js' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

8์ฃผ์ฐจ ์Šคํ„ฐ๋”” Git ๋ช…๋ น์–ด ๋ฐ ๊ฐœ๋… ์ •๋ฆฌ [์ฝ”๋“œ์ž‡ ๋ถ€์ŠคํŠธ ๋ฐฑ์—”๋“œ ์Šคํ„ฐ๋””]  (0) 2024.07.16
6์ฃผ์ฐจ ์Šคํ„ฐ๋”” ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ํ™œ์šฉํ•œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์„œ๋ฒ„ ๋งŒ๋“ค๊ธฐ(2) [์ฝ”๋“œ์ž‡ ๋ถ€์ŠคํŠธ ๋ฐฑ์—”๋“œ ์Šคํ„ฐ๋””]  (3) 2024.07.03
6์ฃผ์ฐจ ์Šคํ„ฐ๋”” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ (2) [์ฝ”๋“œ์ž‡ ๋ถ€์ŠคํŠธ ๋ฐฑ์—”๋“œ ์Šคํ„ฐ๋””]  (1) 2024.06.30
6์ฃผ์ฐจ ์Šคํ„ฐ๋”” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ (1) [์ฝ”๋“œ์ž‡ ๋ถ€์ŠคํŠธ ๋ฐฑ์—”๋“œ ์Šคํ„ฐ๋””]  (0) 2024.06.28
5์ฃผ์ฐจ ์Šคํ„ฐ๋”” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์›น ๊ฐœ๋ฐœ ๊ธฐ๋ณธ๊ธฐ (4) async/await์„ ํ™œ์šฉํ•œ ์„ธ๋ จ๋œ ๋น„๋™๊ธฐ ์ฝ”๋“œ [์ฝ”๋“œ์ž‡ ๋ถ€์ŠคํŠธ ๋ฐฑ์—”๋“œ ์Šคํ„ฐ๋”” ]  (2) 2024.06.04