개요
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 써가며 findMenuByMenuId 와 createOrderItem로 각각 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