Django orm을 Sequelize로 그걸 다시 Raw Query로

성종호·2022년 5월 8일
0
post-custom-banner

Django orm에서 Node Sequelize로 그걸 다시 Raw Query로 변환

취업을위해, 공부를위해 계속해서 진행했던 프로젝트를 리팩토링, 변환하는 작업중
면접을 진행하면서 orm을 사용한것 까지는 좋았다. 하지만 쿼리문에 대한 질문도 굉장히 많이 받았고 부족함을 알고있었지만 이제서야 변환을 하게 되었다.

일단 먼저 아쉬운점을 나열해보겠다.

  1. 배포되어있는 Python Django 프로젝트와 똑같은 데이터를 넘겨주기위해
    sequelize, Raw Query도 재가공을 해줘야 했던점
  2. orm의 편리함을 느꼈던 부분인데 1:M의 join과정에서 예를들어 하나의 주문 명세서의 주문한 상품 데이터를 가져와야 하는 상황에서
Sequelize 
[{
	id: 74,
    order_number: "de30403c-4409-48a3-a8b0-a1e71dda68c7",
    order_status_id: 1,
    users_id: 5,
    products: [{id: 1}, {id: 2}]
}]

products를 보면 orm같은경우 이런식으로 값을 배열안에 객체형태로 알아서 반환을 해준다.

하지만 Raw Query같은경우

Raw Query
[
{
	id: 74,
    order_number: "de30403c-4409-48a3-a8b0-a1e71dda68c7",
    order_status_id: 1,
    users_id: 5,
    productId: 1
},
{
	id: 74,
    order_number: "de30403c-4409-48a3-a8b0-a1e71dda68c7",
    order_status_id: 1,
    users_id: 5,
    productId: 2
},
]

이런식으로 주문명세서 id: 74는 주문상품의 갯수만큼 계속해서 나오게 된다는점
그래서 객체안의 요소를 배열로 받는방법을 여러 찾아봤지만 현재는 답을 찾지 못한 상태 이다.


일단 전체 코드를 보이기엔 길어지니 이커머스 프로젝트인 brokurly의 order 기능구현에 대해서만 코드올려놓겠다.


Django orm

GET order (Django orm)

@login_required
    def get(self, request):
            orders = Order.objects.filter(users=request.user).select_related("order_status")\
                                                             .prefetch_related("orderitem_set__product__image_set",
                                                                               "orderitem_set__order_items_status").order_by("-created_at")
           
            result=[{
                "order_id"     : order.id,
                "order_number" : order.order_number,
                "order_status" : order.order_status.status,
                "products"     : [{
                    "id"       : orderItem.product.id,
                    "name"     : orderItem.product.name,
                    "image"    : orderItem.product.image_set.all()[0].url,
                    "price"    : orderItem.product.price,
                    "quantity" : orderItem.quantity,
                    "status"   : orderItem.order_items_status.status,
                } for orderItem in order.orderitem_set.all()]
            } for order in orders]
    

Sequelize orm

GET order (Sequelize orm)
const getOrder = async(user)=>{
    const order = await db.Order.findAll({
        include: {
            model: db.OrderStatus,
            model: db.OrderItem,
            include:{
                model: db.Product,
                model: db.OrderItemStatus,
                include: {
                    model: db.Image,
                    attributes: ['url']
                }
            }
        },
        where: {
            users_id: user
        }
    }).catch((err)=>{
        throw {status: 400, message: err.message}
    })

    return order
}

Raw query

GET order (Raw query)

const getOrderDao = async(user)=>{
    return await db.sequelize.query(
        `
        SELECT o.id, o.order_number, os.status,
        GROUP_CONCAT(p.id SEPARATOR '|') AS productId,
        GROUP_CONCAT(p.name SEPARATOR '|') AS productName,
        GROUP_CONCAT(p.price SEPARATOR '|') AS productPrice,
        GROUP_CONCAT(ois.status SEPARATOR '|') AS itemStatus
        FROM orders AS o
        INNER JOIN order_status AS os
        ON (os.id = o.order_status_id)
        INNER JOIN order_items AS oi
        ON (oi.order_id = o.id)
        INNER JOIN order_item_status AS ois
        ON (ois.id = oi.order_items_status_id)
        INNER JOIN products AS p
        ON (p.id = oi.product_id)
        LEFT OUTER JOIN images AS i
        ON (i.product_id = p.id)
        WHERE o.users_id = ${user}
        GROUP BY o.id, o.order_number, os.status
        `
    ).catch((e)=> {
        throw {status:500, message:e.message}
    })
}

이런식으로 변경하였고 바꾸게될경우 Response해줘야할 key값들이 바뀌어야 하거나 Sequelize나 Raw Query 같은경우에는 재가공을 해줘야 할것같다.

GROUP_CONCAT 을 쓸경우 문자열안에 내가정한 기호로 여러값을 구분지을수 있는데 이부분도 쿼리문에 대해 더 공부를 해봐야 할것 같다.

profile
아자
post-custom-banner

0개의 댓글