-
2019-08-19 개발일지개발일지 2019. 8. 19. 13:14
오늘은 Sequelize를 사용해서 SQL 함수를 사용해야하는 상황이 발생했다.
PostgreSQL의 ROW_NUMBER() OVER() 함수를 이용하여 조회한 대상에 순차번호를 매겨서 프론트 엔드에 데이터를 넘겨야했다.
이는 시퀄라이즈의 options를 이용해서 처리할 수 있었다.
코드를 보자.
const table = await model.findAll({ attributes: [ [ sequelize.literal('ROW_NUMBER() OVER(ORDER BY id ASC)'), 'num' ], [ 'id', 'id' ], [ 'content', 'content' ] ], where: [ something: some ] });
attributes 속성엔 조회 대상 필드에 대한 조작을 할 수 있게 해주는 속성이다.
[ '속성 정의', '별칭' ] 형식으로, 무언가 조작을 한 후에 그에 대한 별칭을 줘서 필드를 조회 결과에 포함해준다.
sequelize의 literal()함수는 문자 그대로를 쿼리에 반영해주는 함수다.
즉 입력한 쿼리를 그대로 쿼리에 반영하여 num이라는 가상 필드로 결과에 포함시켜준다.
공식 문서를 참고했고, 어렵진 않았는데 sequelize의 fn()함수로 할 수 있는 줄 알고 시도 했다가 안되서 literal()을 찾아냈다.
무엇이 안되었냐면 fn()함수는 인자로 SQL 함수명, 인자배열(함수를 적용할 대상 컬럼)을 받는데, ROW_NUMBER()같은 경우에 함수 안에 인자를 넣지 않기 때문에 fn()함수에 fn('ROW_NUMBER()')만 작성할 경우 대상 컬럼을 넣지 않았다며 에러를 내뱉었다.
참고:
https://sequelize.org/master/manual/querying.html#attributes
그리고 시퀄라이즈에서 트랜잭션을 처리하는 방법을 알았다.
공식문서 예제는 Promise기반으로 체이닝으로 처리하는 방법으로 보여줬는데 현재 async await를 이용해서 코딩하고 있어서 문법을 맞게끔 바꿔봤다.
let transaction = null; try { transaction = await Model().sequelize.transaction(); let table = await Model().findByPk(id); table = await table.update({ deleteFlag: true }, { transaction }); // throw new Error(); // 트랜잭션 테스트 await transaction.commit(); return res.json({ message: 'test 성공' }); } catch (error) { await transaction.rollback(); }
Model 객체의 sequelize 속성의 transaction() 함수를 할당한다.
이 때 await 구문을 사용하니 try/catch로 에러 핸들링을 수행한다.
만약 코드 처리 도중 commit()을 수행하기 전 에러가 발생하여 catch로 위치가 변경될 경우 rollback()로 실행을 롤백해준다.
'개발일지' 카테고리의 다른 글
2019-08-21 개발일지 (0) 2019.08.21 2019-08-20 개발일지 (0) 2019.08.20 2019-08-16 개발일지 (0) 2019.08.17 휴가기간 (2019-08-12 ~ 2019-08-15) (0) 2019.08.12 2019-08-09 개발일지 (0) 2019.08.10