ORM: Sequelize: MySQL쿼리를 Sequelize 쿼리로 바꾸고싶습니다.
조회수 1198회
우선 데이터와 테이블을 아래와 같습니다.
CREATE TABLE products
(
p_id INT,
p_name VARCHAR(32),
PRIMARY KEY (p_id)
);
CREATE TABLE color
(
p_id INT,
p_color VARCHAR(24)
);
CREATE TABLE size
(
p_id INT,
p_size VARCHAR(12)
);
INSERT INTO products
VALUES
(1, 'test1'),
(2, 'test2'),
(3, 'test3'),
(4, 'test4'),
(5, 'test5');
INSERT INTO color
VALUES
(1, 'black'),
(1, 'white'),
(1, 'gray'),
(2, 'black'),
(2, 'beige'),
(3, 'blue'),
(3, 'red'),
(3, 'green'),
(4, 'black'),
(4, 'white'),
(4, 'beige'),
(4, 'gray'),
(4, 'mustard'),
(5, 'black'),
(5, 'white');
INSERT INTO size
VALUES
(1, 'S'),
(1, 'M'),
(1, 'L'),
(1, 'XL'),
(2, 'Free'),
(3, 'XS'),
(3, 'S'),
(3, 'M'),
(3, 'L'),
(3, 'XL'),
(4, 'M'),
(4, 'L'),
(4, 'XL'),
(5, 'Free');
sql문으로 콘솔에서 이렇게 넣는 쿼리를 sequelize에서 넣는 쿼리로 바꾸고싶습니다.
SELECT p.p_Id, p.p_name, s.p_size, c.p_color
FROM products AS p
LEFT OUTER JOIN size AS s
ON p.p_id = s.p_id
LEFT OUTER JOIN color AS c
ON p.p_id = c.p_id;
+-----------+-------------+-------------+--------------+
| productId | productName | productSize | productColor |
+-----------+-------------+-------------+--------------+
| 1 | test_1 | S | black |
| 1 | test_1 | M | black |
| 1 | test_1 | L | black |
| 1 | test_1 | XL | black |
| 1 | test_1 | S | white |
| 1 | test_1 | M | white |
| 1 | test_1 | L | white |
| 1 | test_1 | XL | white |
| 1 | test_1 | S | gray |
| 1 | test_1 | M | gray |
| 1 | test_1 | L | gray |
| 1 | test_1 | XL | gray |
| 2 | test_2 | Free | black |
| 2 | test_2 | Free | beige |
| 3 | test_3 | XS | blue |
| 3 | test_3 | S | blue |
| 3 | test_3 | M | blue |
| 3 | test_3 | L | blue |
| 3 | test_3 | XL | blue |
| 3 | test_3 | XS | red |
| 3 | test_3 | S | red |
| 3 | test_3 | M | red |
| 3 | test_3 | L | red |
| 3 | test_3 | XL | red |
| 3 | test_3 | XS | green |
| 3 | test_3 | S | green |
| 3 | test_3 | M | green |
| 3 | test_3 | L | green |
| 3 | test_3 | XL | green |
| 4 | test_4 | M | black |
| 4 | test_4 | L | black |
| 4 | test_4 | XL | black |
| 4 | test_4 | M | white |
| 4 | test_4 | L | white |
| 4 | test_4 | XL | white |
| 4 | test_4 | M | beige |
| 4 | test_4 | L | beige |
| 4 | test_4 | XL | beige |
| 4 | test_4 | M | gray |
| 4 | test_4 | L | gray |
| 4 | test_4 | XL | gray |
| 4 | test_4 | M | mustard |
| 4 | test_4 | L | mustard |
| 4 | test_4 | XL | mustard |
| 5 | test_5 | Free | black |
| 5 | test_5 | Free | white |
+-----------+-------------+-------------+--------------+
46 rows in set (0.00 sec)
models.products.findAll({
include: [{
model: models.size,
required: false,
}, {
model: models.color,
required: false
}]
});
물론 색상, 사이즈 테이블에서는 p_id
가 여러 개이기 때문에 PK
설정을 할 수가 없어
위와 같이 쿼리를 실행하니까 products
테이블에서만 제약을 설정했습니다. 그리고 p_id
가 테이블마다 공통으로 오는 컬럼이기 때문에 FK
를 p_id
로만 설정을 해뒀구요.
SELECT
`p`.`p_id`,
`p`.`p_name`,
`s`.`p_id` AS `s.p_id`,
`s`.`p_id` AS `s.p_id`,
`s`.`p_size` AS `s.p_size`,
`c`.`p_id` AS `c.p_id`,
`c`.`p_id` AS `c.p_id`,
`c`.`p_color` AS `c.p_color`,
FROM `products` AS `p`
LEFT OUTER JOIN `size` AS `s`
ON `p`.`p_id` = `s`.`id`
LEFT OUTER JOIN `color` AS `c`
ON `p`.`p_id` = `c`.`id`
같이 나와버립니다. 제가 의도한 바는 ON
절에서 p.p_id = c.p_id
가 되어야 하는데 색상 테이블에는 있지도 않은 컬럼이 와서 p.p_id = c.id
로 떠버립니다. ON
절을 sequelize 수준에서 생쿼리를 쓰지 않고 해결하는 방법을 알고 계시는 분께 도움을 요청하는 바입니다.
-
(•́ ✖ •̀)
알 수 없는 사용자
1 답변
-
질문 드리고 나서
association
도 잡아봤고요. 그리고sequelize-cli
고질적인 문제가id
,updatedAt
,createdAt
이migrations
에 자동으로 생성되서 생기는 문제도 관련 메소드로 해결했습니다. 코드는 아래와 같습니다.products.hasMany(db.size, { foreignKey: 'p_id' }); products.hasMany(db.color, { foreignKey: 'p_id' }); color.belongsTo(db.products, { foreignKey: 'p_id' }); size.belongsTo(db.products, { foreignKey: 'p_id' }); db.ProductColor.removeAttribute('id'); db.ProductSize.removeAttribute('id');
웃기는게
belongsTo()
를 없애고hasMany()
로만 관계설정을 해줘도 JSON 데이터가 반환되더라구요.let productId = req.params.id; const product = products.findAll({ where: { p_id: productId }, include: [{ model: size, attributes: { exclude: ['p_id', 'id', 'createdAt', 'updatedAt'] } }, { model: color, attributes: { exclude: ['p_id', 'id', 'createdAt', 'updatedAt'] } }] });
이렇게 쿼리를 작성했습니다.
p_id
는 products 테이블과 중복돼서 제거했고,createdAt
,updatedAt
은 테이블에 존재하지 않는 데이터라 제거했습니다. 마지막으로id
는 아까removeAttribute()
를 사용해서 따로 제외하지 않아도 딱히 등장하지는 않더라구요. 반환된 JSON 데이터는 다음과 같습니다.{ "product": [ { "p_id": 1, "p_ame": "test_1", "createdAt": "2018-10-13T00:00:00.000Z", "updatedAt": "2018-10-14T00:00:00.000Z", "size": [ { "size": "S" } ], "color": [ { "color": "black" } ] } ] }
이렇게 나옵니다. size 테이블에
p_id
가 1인 레코드들은 4개고 color 테이블에는 3개인데 위에서는 1개씩밖에 안나오니 너무 답답하네요."size": [ { "productSize": "S" }, { "productSize": "M" }, { "productSize": "L" }, { "productSize": "XL" } ], "color": [ { "productColor": "black" }, { "productColor": "white" }, { "productColor": "gray" } ]
이 경우가 다대다는 아닌거같아서 연결테이블은 만들지 않았습니다. 도움이 절실합니다. 뭐가 문제인지를 모르겠네요 ㅠㅠ
-
(•́ ✖ •̀)
알 수 없는 사용자
- left outer join 관련해서 찾아보니 include 의 required 가 true 냐 false 냐에 따라 결과가 다른가 본데요. 잘 모르면서 아무거나 막 찾아와 혼란만 드리고 있는 건 아닌지 모르겠지만... https://blog.kozakana.net/2018/04/sequelize_join/ 엽토군 2019.1.23 23:15
- 엽토군님 답변 달아주셔 감사합니다^^ required옵션은 작성안하면 자동으로 false가 돼서 LEFT OUTER JOIN이 되고 true로 옵션을 주면 INNER JOIN이 됩니다. 그래서 required를 따로 작성해주지 않았습니다. raw: true옵션으로 어찌저찌 해결했습니다만 데이터 모양이 이쁘게 나오진 못하더라구요. https://github.com/sequelize/sequelize/issues/5193#issuecomment-386153316 링크 타고 들어가셔서 한번 봐두시면 좋을 것같습니다. 절 도와주는 분이 계신다는데 크게 감사하고 있습니다. 다시한번 답글 달아주셔서 감사합니다 :) 알 수 없는 사용자 2019.1.24 11:47
-
댓글 입력