[TIL] Day 48 : prisma에서 제공하는 여러 데이터를 배열로 한 번에 CRUD하는 방법

Q·2024년 6월 25일

TIL

목록 보기
49/59

개요

MySQL에는 당연히 있겠지만,
prisma에도 여러 데이터를 동시에 Create, Read, Update, Delete 하는 방법이 존재한다.

그런데 이 중에서 Read 는 findMany method를 자주 써와서 익숙했기도 하고, 특정 조건 '하나(여러 조건이라도 AND, OR 로 결국 하나의 조건이 된다)'에 부합하는 여러 데이터를 조회하는 거였다.

나머지 셋 중에 Delete는 Read랑 비슷하게 하면 될 것 같지만,
Create, Update는 각각 삽입/수정 해야할 데이터의 조건이나 값이 다를 수 있기 때문에 어떤 식으로 할 수 있는 것인지 감이 오지 않았다.

그래서 찾아본 결과, Create, Update 할 데이터를 배열로 넣어서 처리하면 된다.

findMany, createMany 예시 - 수정 전

  • order.service.js 내부
// 주문 메뉴 데이터 생성
for (const item of orderItems) {
	const menuId = item.menuId;
	const menu = await this.menuRepository.findMenuByMenuId(menuId);
	await this.orderItemRepository.createOrderItem(createdOrder.id, item.menuId, menu.price, item.quantity, { tx });
}

create 할 데이터 orderItems가 배열로 주어질 때,
이 배열을 for loop으로 돌면서 하나하나 await 써가며 findMenuByMenuIdcreateOrderItem로 각각 menu table과 order table 두 곳에 접근한다.

  • menu.repository.js 내부
// menu 테이블에서 메뉴 데이터 조회
findMenuByMenuId = async (menuId) => {
    const menu = await this.prisma.menu.findUnique({
      where: { id: Number(menuId) },
    });
    return menu;
};
  • order-item.repository.js 내부
// order_items 테이블에 데이터 생성
createOrderItem = async (orderId, menuId, price, quantity) => {
    await this.prisma.orderItem.create({
      data: { orderId, menuId, price, quantity },
    });
};

그런데 이는 리소스 낭비가 심한, 너무나 비효율적인 방법이다.

따라서, create 할 데이터 포맷을 배열로 미리 만들어 놓고,
아래와 같이 findMany, createMany를 써서 DB에 한 번에 접근해서 처리하는 것이 좋다.

findMany, createMany 예시 - 수정 후

  • order.service.js 내부
// 조회할 데이터의 menuId를 배열로 만드는 작업
const orderMenuIds = orderItems.map((item) => item.menuId);

// menu 테이블에서 findMany를 사용하는 method를 이용해 한 번에 조회
const validOrderItems = await this.menuRepository.findMenusByMenuIds(orderMenuIds);

// order_items 테이블에 createMany로 생성할 데이터 배열을 포맷하는 작업
const orderItemData = validOrderItems.map((item) => ({
	orderId: createdOrder.id,
	menuId: item.menuId,
	price: item.price,
	quantity: item.quantity,
}));

// order_items 테이블에 createMany를 사용하는 methodfmf 이용해 데이터를 한꺼번에 생성
await this.orderItemRepository.createOrderItems(orderItemData);
  • menu.repository.js 내부
// menuId의 배열로 메뉴 목록 조회
findMenusByMenuIds = async (menuIds) => {
	const menus = await this.prisma.menu.findMany({
      where: {
        id: { in: menuIds },
      },
    });
    return menus;
};
  • order-item.repository.js 내부
// 주문 메뉴 목록을 배열로 받아서 데이터 생성
createOrderItems = async (orderItemData) => {
    await this.prisma.orderItem.createMany({
      data: orderItemData,
    });
};

deleteMany 예시 - 수정 전

  • order.service.js 내부
// 카트 가져오기
const cart = await this.cartRepository.getMyCartByCustomerId(customerId);
const menuIdsInCart = cart.map((cartItem) => cartItem.menuId);


// 장바구니에서 주문한 메뉴 삭제
for (const item of orderItems) {
	if (menuIdsInCart.includes(item.menuId)) {
	await this.cartRepository.deleteCartItemByMenuId(customerId, item.menuId);
	}
}
  • cart-item.repository.js 내부
// cart_items 테이블에서 데이터 하나 삭제
deleteCartItemByMenuId = async (customerId, menuId) => {
    return await this.prisma.cartItem.delete({
      where: { customerId_menuId: { customerId, menuId } },
    });
};

deleteMany - 수정 후

  • order.service.js 내부
// cart_items 테이블에서 삭제할 데이터를 배열로 포맷하는 작업
const toBeDeleted = orderItemData.map((item) => ({
	customerId: customerId,
	menuId: item.menuId,
}));
  • cart-item.repository.js 내부
// 삭제할 장바구니 아이템 목록을 배열로 받아서 데이터 삭제
deleteCartItems = async (toBeDeleted) => {
    return await this.prisma.cartItem.deleteMany({
      where: { OR: toBeDeleted }, 
    });
};

OR operator in Prisma allows you to match any of the conditions in the array

참고: Prisma/docs

0개의 댓글