[ORM] ๐ ์ํ๋ผ์ด์ฆ - ์ฟผ๋ฆฌ ๋ฌธ๋ฒ ์ ๋ฆฌ
์ํ๋ผ์ด์ฆ ์ฟผ๋ฆฌ๋ฌธ
CRUD ์์ ์ ํ๊ธฐ ์ํด์ ๋จผ์ ์ํ๋ผ์ด์ฆ ์ฟผ๋ฆฌ๋ฅผ ์์์ผํ๋ค.
SQL๋ฌธ์ ์๋ฐ์คํฌ๋ฆฝํธ๋ก ์์ฑํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์, ์ํ๋ผ์ด์ฆ์ ๋ฐฉ์์ ์ฌ์ฉํด์ผ ํ๋ค.
์ํ๋ฆฌ์์ง ์ฟผ๋ฆฌ๋ฌธ์ ๋น๋๊ธฐ๋ก ๋์ํ๋ฉฐ ํ๋ก๋ฏธ์ค ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ฏ๋ก, then์ ๋ถ์ฌ ๊ฒฐ๊ณผ๊ฐ์ ๋ฐ์ ์ ์๋ค.
๊ทธ๋์ async/await ๋ฌธ๋ฒ๊ณผ ํจ๊ป ์ฌ์ฉํ ์๋ ์๋ค.
ํ ์ด๋ธ ์กฐํ (findAll, findOne)
findAll
- ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๋ฐฐ์ด ๊ฐ์ฒด๋ก ๋ฐํ
๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ์กฐํํ๊ณ ์ถ์ผ๋ฉด findAll ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ค.
const { User } = require('./models');
// usersํ
์ด๋ธ ์ ์ฒด๋ฅผ ์กฐํํด์ ๊ทธ ๊ฒฐ๊ณผ๊ฐ์ ๊ฐ์ฒด๋ก ๋ง๋ค์ด user๋ณ์์ ๋ฃ์ด์ค๋ค.
const user = User.findAll({});
// user๋ณ์์๋ ์กฐํ๋ ๊ฒฐ๊ณผ ๊ฐ์ฒด๊ฐ ๋ค์ด์์ด์, ํด๋น ํ
์ด๋ธ ์ปฌ๋ผ๋ค์ ์กฐํํ ์ ์๋ค.
console.log(user[0].comment) // findAll๋ ์ฌ๋ฌ ํ๋ค์ ์กฐํํ๊ธฐ์, ๊ฐ ํ๋ค์ด ๋ฐฐ์ด๋ก ์ ์ฅ๋์ด์๋ค.
// ๋ฐ๋ผ์ ๋ฐฐ์ด ์ธ๋ฑ์ค๋ก ์กฐํํ๋ค. ์ฒซ๋ฒ์งธ ํ usersํ
์ด๋ธ์ commentํ๋๋ฅผ ์กฐํํ๊ธฐ
์์ ์ํ๋ผ์ด์ฆ ์ฟผ๋ฆฌ๋ฌธ์ ๋ค์ SQL๋ฌธ ์ฒ๋ผ ๋์ํ๋ค.
SELECT * FROM users;
findOne
- ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ฒด๋ก ๋ฐํ
ํ ์ด๋ธ์ ๋ฐ์ดํฐ๋ฅผ ํ๋๋ง ๊ฐ์ ธ์จ๋ค.
const { User } = require('./models');
// usersํ
์ด๋ธ ์ ์ฒด๋ฅผ ์กฐํํด์ ๊ทธ ๊ฒฐ๊ณผ๊ฐ์ ๊ฐ์ฒด๋ก ๋ง๋ค์ด user๋ณ์์ ๋ฃ์ด์ค๋ค.
const user = User.findOne({});
// user๋ณ์์๋ ์กฐํ๋ ๊ฒฐ๊ณผ ๊ฐ์ฒด๊ฐ ๋ค์ด์์ด์, ํด๋น ํ
์ด๋ธ ์ปฌ๋ผ๋ค์ ์กฐํํ ์ ์๋ค.
console.log(user.comment) // findOne๋ ํ๋๋ง ์กฐํ๋๋ค. usersํ
์ด๋ธ์ commentํ๋๋ฅผ ์กฐํํ๊ธฐ
์์ ์ํ๋ผ์ด์ฆ ์ฟผ๋ฆฌ๋ฌธ์ ๋ค์ SQL๋ฌธ ์ฒ๋ผ ๋์ํ๋ค.
SELECT * FROM users limit 1;
์กฐ๊ฑด ์กฐํ (attributes, where)
attributes ์ต์ ์ ์ฌ์ฉํ์ฌ ์ํ๋ ์ปฌ๋ผ๋ง ๊ฐ์ ธ์ฌ ์๋ ์๋ค.
๋ํ, where ์ต์ ์ผ๋ก ์กฐ๊ฑด๋ค์ ๋์ดํ ์๋ ์๋ค. where ์ต์ ์ ๊ธฐ๋ณธ์ ์ผ๋ก AND ์ต์ ๊ณผ ๊ฐ๋ค.
const { User } = require('./models');
const { Op } = require('sequelize');
const user = User.findAll({
attributes: ['name', 'age'],
where: {
married: true, // married = 1
age: { [Op.gt]: 30 }, // age > 30;
},
});
console.log(user.comment)
SELECT name, age FROM users WHERE married = 1 AND age > 30;
๋น๊ต ๊ตฌ๋ฌธ์ด ์กฐ๊ธ ํน์ดํ๋ฐ, ์ํ๋ผ์ด์ฆ๋ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ์ฌ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ๊ธฐ ๋๋ฌธ์ ํน์ํ ์ฐ์ฐ์๋ค์ด ์ฌ์ฉ๋๋ค.
๋ค์์ ์ํ๋ผ์ด์ ํน์ ์ฐ์ฐ์ ์ ๋ฆฌ์ด๋ค.
๐ก ์์ฃผ ์ฐ์ด๋ Op๊ฐ์ฒด
Op.gt | ์ด๊ณผ |
Op.gte | ์ด์ |
Op.lt | ๋ฏธ๋ง |
Op.lte | ์ดํ |
Op.ne | ๊ฐ์ง ์์ |
Op.or | ๋๋ |
Op.in | ๋ฐฐ์ด ์์ ์ค ํ๋ |
Op.notIn | ๋ฐฐ์ด ์์์ ๋ชจ๋ ๋ค๋ฆ |
const Op = Sequelize.Op
[Op.and]: [{a: 5}, {b: 6}] // (a = 5) AND (b = 6)
[Op.or]: [{a: 5}, {a: 6}] // (a = 5 OR a = 6)
[Op.gt]: 6, // > 6
[Op.gte]: 6, // >= 6
[Op.lt]: 10, // < 10
[Op.lte]: 10, // <= 10
[Op.ne]: 20, // != 20
[Op.eq]: 3, // = 3
[Op.is]: null // IS NULL
[Op.not]: true, // IS NOT TRUE
[Op.between]: [6, 10], // BETWEEN 6 AND 10
[Op.notBetween]: [11, 15], // NOT BETWEEN 11 AND 15
[Op.in]: [1, 2], // IN [1, 2]
[Op.notIn]: [1, 2], // NOT IN [1, 2]
[Op.like]: '%hat', // LIKE '%hat'
[Op.notLike]: '%hat' // NOT LIKE '%hat'
[Op.startsWith]: 'hat' // LIKE 'hat%'
[Op.endsWith]: 'hat' // LIKE '%hat'
[Op.substring]: 'hat' // LIKE '%hat%'
[Op.regexp]: '^[h|a|t]' // REGEXP/~ '^[h|a|t]' (MySQL/PG only)
[Op.notRegexp]: '^[h|a|t]' // NOT REGEXP/!~ '^[h|a|t]' (MySQL/PG only)
[Op.like]: { // LIKE ANY ARRAY['cat', 'hat'] - also works for iLike and notLike
[Op.any]: ['cat', 'hat']
}
[Op.gt]: { // > ALL (SELECT 1)
[Op.all]: literal('SELECT 1')
}
Op.or์ ๋ค์๊ณผ ๊ฐ์ด ๋ฐฐ์ด ๋ด์ ์ ์ฉํ ์ฟผ๋ฆฌ๋ค์ ๋์ดํ์ฌ ์ฌ์ฉํ๋ค.
const user = User.findAll({
attributes: ['name', 'age'],
where: {
[Op.or]: [ // married = 0 or age > 30
{ married: false },
{ age: { [Op.gt]: 30 } }
],
},
});
console.log(user.comment)
SELECT name, age FROM users WHERE married = 1 OR age > 30;
๋ฐ์ดํฐ ๋ฃ๊ธฐ (Create)
๋ชจ๋ธ์ ๋ถ๋ฌ์ create ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ก์ฐ๋ฅผ ์์ฑํ๋ค.
์ฌ๊ธฐ์ ํ๊น๋ฆฌ๋๊ฒ SQL์์์ create๋ ํ ์ด๋ธ์ ๋ง๋๋ ๊ฑฐ์ง๋ง ORM์์์ create๋ insert๋ก ์ฐ์ธ๋ค๋ ์ ์ ์์งํ์.
const result = User.create({ // ์์ฑ๋ ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ์ป๋๋ค.
name: 'beom seok',
age: 23,
married: false,
comment: '์๋
ํ์ธ์.'
});
INSERT INTO users (name, age, married, comment)
VALUES ('beom seok', 23, 0, '์๋
ํ์ธ์.');
์ฃผ์ํด์ผํ ์ ์ ๋ฐ์ดํฐ๋ฅผ ๋ฃ์ ๋ MySQL์ ์๋ฃํ์ด ์๋ ์ํ๋ผ์ด์ฆ ๋ชจ๋ธ์ ์ ์ํ ์๋ฃํ๋๋ก ๋ฃ์ด์ผํ๋ค.
๊ฐ๋ น married์ ๊ฒฝ์ฐ ์ค์ MySQL์๋ TINYINT๋ก ๋์ด ์ด์ ์ 0์ ๋ฃ์ด์ฃผ์์์ง๋ง, ํ์ฌ๋ BOOLEAN์ผ๋ก ์ ์๋ผ์์ผ๋ฏ๋ก false๋ฅผ ๋ฃ์ด์ฃผ์ด์ผ ํ๋ค.
์๋ฃํ ๋๋ ์ต์ ์ ๋ถํฉํ์ง ์๋ ๋ฐ์ดํฐ๋ฅผ ๋ฃ์ ๊ฒฝ์ฐ ์ํ๋ผ์ด์ฆ๊ฐ ์๋ฌ๋ฅผ ๋ฐ์์ํค๋ฉฐ, ์ํ๋ผ์ด์ฆ๊ฐ ์์์ MySQL ์๋ฃํ์ผ๋ก ๋ฐ๊ฟ์ฃผ๋ ๊ฑฑ์ ๋ง์.
findOrCreate()
findOrCreate() ๋ผ๋ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ์กฐํ ํ์ ์๋ ๊ฐ์ด๋ฉด ์์ฑํ๊ณ , ์๋ ๊ฐ์ด๋ฉด ๊ทธ ๊ฐ์ ๊ฐ์ ธ์ค๋ ํํ์ ์คํผ๋ ์ด์ ๋ ๊ฐ๋ฅํ๋ค.
// find์ create ๋ ์กฐ๊ฑด์ ์ดํํ๊ธฐ ๋๋ฌธ์ ๋ฐํ๊ฐ์ด 2๊ฐ ์ฆ ๋ฐฐ์ด์ด๋ค.
const [user, created] = await User.findOrCreate({
where: { username: 'sdepold' },
defaults: {
job: 'Technical Lead JavaScript'
}
});
if (created) {
// ๋ง์ฝ findํ์ง ๋ชปํ์ฌ ์๋ก create ๋ ๊ฒฝ์ฐ
console.log(user.job); // 'Technical Lead JavaScript'
} else {
// ๋ง์ฝ find๊ฐ ๋ ๊ฒฝ์ฐ
}
where์ ํจ๊ป ์ ๋ฌ๋๋ defaults ์ต์ ์ ๊ฒ์ ๊ฒฐ๊ณผ๊ฐ ์กด์ฌํ์ง ์์ ๊ฒฝ์ฐ ์๋ก ์์ฑ๋๋ ์์๊ฐ ๊ฐ๋ ๊ธฐ๋ณธ๊ฐ์ด๋ค.
์ ๋ ฌ (order)
์ ๋ ฌ์ order ์ต์ ์ผ๋ก ์ฒ๋ฆฌํ๋ค.
2์ฐจ์ ๋ฐฐ์ด์ด๋ผ๋ ์ ์ ์ฃผ์ํ์. ์ด๋ ์ ๋ ฌ์ ๊ผญ ์ปฌ๋ผ ํ๋๊ฐ ์๋ ๋ ๊ฐ ์ด์์ผ๋ก๋ ํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
User.findAll({
attributes: ['name', 'age'],
order: [ ['age', 'DESC'], ['name', 'ASC'] ]
});
SELECT id, name FROM users ORDER BY age DESC name ASC;
ํ์ด์ง (limit, offset)
์กฐํํ ๋ก์ฐ ๊ฐ์๋ limit์ผ๋ก,
์กฐํ๋ฅผ ์์ํ ๋ก์ฐ ์์น๋ offset์ผ๋ก ํ ์ ์๋ค.
User.findAll({
attributes: ['name', 'age'],
order: [['age', 'DESC']],
limit: 10,
offset: 5,
});
SELECT id, name FROM users ORDER BY age DESC LIMIT 5, 10;
SELECT id, name FROM users ORDER BY age DESC LIMIT 10 OFFSET 5;
limit์ด 1์ด๋ผ๋ฉด findAll ๋์ findOne์ ์ฌ์ฉํ ์ ์๋ค.
์์ (Update)
update ๋ฉ์๋๋ก ์์ ํ ์๋ ์๋ค.
์ฒซ ๋ฒ์งธ ์ธ์๋ ์์ ํ ๋ด์ฉ์ด๊ณ , ๋ ๋ฒ์งธ ์ธ์๋ ์ด๋ค ๋ก์ฐ๋ฅผ ์์ ํ ์ง์ ๋ํ ์กฐ๊ฑด์ด๋ค.
where ์ต์ ์ ์กฐ๊ฑด๋ค์ ์ ๋๋ค.
User.update({
comment: '์๋ก์ด ์ฝ๋ฉํธ.',
}, {
where: { id: 2 },
});
UPDATE users SET comment = '์๋ก์ด ์ฝ๋ฉํธ.' WHERE id = 2;
upsert()
update์ / insert ํฉ์ฑ ๋ฒ์ ผ.
๋ฌธ๋ฒ์ ์์์ ๋ฐฐ์ด findorcreate์ ๋ณ ๋ค๋ฅด์ง ์๋ค.
const [city, created] = await City.upsert({
cityName: "York",
population: 20000,
});
console.log(created); // true or false
console.log(city); // City object
INSERT INTO Cities (cityName, population)
VALUES (?, ?)
ON DUPLICATE KEY
UPDATE
`cityName` = VALUES (`cityName`),
`population` = VALUES (`population`);
์ญ์ (Delete)
๋ก์ฐ ์ญ์ ๋ destroy ๋ฉ์๋๋ก ์ญ์ ํ๋ค.
User.destroy({
where: { id: 2 },
});
User.destroy({
where: { id: { [Op.in]: [1,3,5] } },
});
DELETE FROM users WHERE id = 2;
DELETE FROM users WHERE id in(1,3,5);
์ํ๋ผ์ด์ฆ ๊ด๊ณ ์ฟผ๋ฆฌ๋ฌธ
include
์์ ์ฌ์ง์ฒ๋ผ, ํ์ฌ User ๋ชจ๋ธ์ Commenter ๋ชจ๋ธ๊ณผ hasMany-belongsTo ๊ด๊ณ๊ฐ ๋งบ์ด์ ธ ์์ผ๋ฉฐ, ๋ง์ฝ ํน์ ์ฌ์ฉ์๋ฅผ ๊ฐ์ ธ์ค๋ฉด์ ๊ทธ ์ฌ๋์ ๋๊ธ๊น์ง ๋ชจ๋ ๊ฐ์ ธ์ค๊ณ ์ถ๋ค๋ฉด include ์์ฑ์ ์ฌ์ฉํ๋ฉด ๋๋ค.
๊ด๊ณ๊ฐ ์๋ ๋ชจ๋ธ์ include ๋ฐฐ์ด์ ๋ฃ์ด์ฃผ๋ฉด ๋๋ค.
๋ฐฐ์ด์ธ ์ด์ ๋ ๋ค์ํ ๋ชจ๋ธ๊ณผ ๊ด๊ณ๊ฐ ์์ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
๋๊ธ์ ์ฌ๋ฌ ๊ฐ์ผ ์ ์์ผ๋ฏ๋ก (hasMany) user.Comments๋ก ์ ๊ทผ ๊ฐ๋ฅํ๋ค.
const user = await User.findOne({
include: [{ // joinํ๋ค.
model: Comment, // joinํ ํ
์ด๋ธ์ ๊ณ ๋ฅธ๋ค.
}]
});
console.log(user.Comments[0]);
// ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ์ธ user๊ฐ์ฒด์์ Comments๋ผ๋ ํค์ includeํ commentsํ
์ด๋ธ ์ฟผ๋ฆฌ๋ค์ด ๋ฐฐ์ด ๊ฐ์ผ๋ก์ ๋ด๊ฒจ ์๋ค.
// Comments ํค์ ์ด๋ฆ์ User๋ชจ๋ธ์ hasMany๋๊น ๋ณต์ํ์ผ๋ก ์๋์ผ๋ก ๋ณํ๋์ ์์ฑ๋ ๊ฒ์ด๋ค. (๊ตฌ๋ถํ๊ธฐ ํธํ๊ฒ)
// => hasOne์ด๋ฉด ๋จ์ํ. M:N์ด๋ฉด ํญ์ ๋ณต์ํ.
select u.*, c.*
from users u
inner join comments c -- sequelize include๋ ๊ธฐ๋ณธ๋์์ inner join์ด๋ค.
on u.id = c.commenter;
get๋ชจ๋ธ๋ช
์์ include๋ก๋ ์ถฉ๋ถํ ๊ด๊ณ๋ฅผ ๋งบ์ด ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ฆด์์์ง๋ง ์ข๋ ๊ฐํธํ ๋ฌธ๋ฒ์ผ๋ก ๊ด๊ณ์ฟผ๋ฆฌ๋ฅผ ์ป์ ์ ์๋๋ฐ, ๋ค์๊ณผ ๊ฐ์ด ๋๊ธ์ ์ ๊ทผํ ์๋ ์๋ค.
๋ฌธ๋ฒ์ด ๋๋ฌด ์ถ์์ ์ด๋ผ include๋ณด๋ค ์ ์๋ฟ์์ ์๊ฒ ์ง๋ง ORM๋ฌธ๋ฒ์ ๊ฐ์ํ์ํค๊ณ ์ง๊ด์ ์ธ ๋ฉ์๋๋ช ์ ์ฌ์ฉํ ์ ์๋ ์ฅ์ ์ด ์๋ค.
const user = await User.findOne({});
const comments = await user.getComments();
// ๋ฐ๋ก includeํ ํ์์์ด ๋ฐ๋ก get๋ฉ์๋๋ฅผ ์ฐ๋ฉด ๋๋ค.
// ์๋ํ๋ฉด associate๋ก ๋ชจ๋ธ์ ์ ์ํ ์๊ฐ ์ํ๋ผ์ด์ ๊ฐ ๊ด๊ณ๊ฐ ๋งบ์ด์ง ๋ฉ์๋๋ฅผ ์์์ ๋ง๋ค์ด ์ฃผ๊ธฐ ๋๋ฌธ์ด๋ค.
console.log(comments);
๊ด๊ณ๋ฅผ ์ค์ ํ๋ค๋ฉด, ์ํ๋ผ์ด์ฆ๋ ๋ค์๊ณผ ๊ฐ์ด
- getComment() / getComments( [ ] ) : ์กฐํ
- setComment() / setComments( [ ] ) : ์์ - ๋จ ํต์งธ๋ก ์ง์ฐ๊ณ ์ถ๊ฐํ๋ ์์ด๋ผ ์กฐ์ฌ
- addComment() / addComments( [ ] ) : ์์ฑ
- removeComment() / removeComments( [ ] ) : ์ญ์
๋ฉ์๋๋ฅผ ๋ง๋ค์ด ์ง์ํ๋ค.
๋์ฌ ๋ค์ ๋ชจ๋ธ์ ์ด๋ฆ์ด ๋ถ๋ ํ์์ผ๋ก ์์ฑ๋๋ค.
s๋ฅผ ๋ถ์ฌ๋ ๋๊ณ ์๋ถ์ฌ๋ ์๊ด ์๋ค.
๋ค๋ง, ๋ณด๊ธฐ ํธํ๊ฒ s๋ฅผ ๋ถ์ธ ๋ฉ์๋๋ ๋ฐฐ์ด์ ์ธ์๋ก ๋ฐ๋ ๊ฒ์ผ๋ก ๊ท์น์ ์ ํด๋์ผ๋ฉด ์ข๋ค.
* ์ด ๋ฐฉ๋ฒ์, DB์ ์์ฒญ์ ๋๋ฒ ๋ณด๋ด์ง๋ง, ํ๋์ ์ฟผ๋ฆฌ๋ง ๊ฐ์ ธ์ค๋ ๊ฒ์ ์ ์ ํ์.
* ํ๋๋ฅผ ๊ฐ์ ธ์ค๋ ์์๋ ๋น์ฐํ ์ค๋ฆ์ฐจ์์ด๋ค.
์กฐํ๋ ์์ ๊ฐ์ด ํ๋ฉด ๋์ง๋ง,
์์ , ์์ฑ, ์ญ์ ๋๋ ์กฐ๊ธ ๋ค๋ฅธ ์ ์ด ์๋ค.
// ์์ฑ
const user = await User.findOne({ ์ต์
}); // ์ฐธ์กฐ ๊ด๊ณ์ ๋ถํฉํ ์ ์ ๋ฅผ ์ ํํ๊ณ
const comment = await Comment.create({ ์ต์
}); // ๋ฐ์ดํฐ๋ฅผ commentํ
์ด๋ธ์ ๋ฃ๋๋ค.
await user.addComment(comment); // user์ ์ธ๋ํค๋ฅผ ๊ด๊ณ์ค์ ๋ comment row์ ์ถ๊ฐ/์
๋ ํ๋ค
// ๋ง์ผ user์ ์ธ๋ํค๋ฅผ ์ Comment.create()๊ณผ์ ์์ ๋ฃ์๋ค๋ฉด ๊ตณ์ด addComment() ์ฟผ๋ฆฌ๋ฅผ ์๋ ๋ ค๋ ๋๋ค.
// FK๊ฐ nullํ์ฉ์ด๊ณ insert๊ณผ์ ์์ FK์ ๋ฐ์ดํฐ๋ฅผ ์๋ฃ์์ ๊ฒฝ์ฐ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค.
// ์ฌ๋ฌ ๊ฐ ์์ฑ
const user = await User.findOne({ ์ต์
});
const comment1 = await Comment.create({ ์ต์
});
const comment2 = await Comment.create({ ์ต์
});
await user.addComment([comment1, comment2]);
insert into comments (ํ๋)
( select ํ๋ from user where ์กฐ๊ฑด )
๊ด๊ณ ์ฟผ๋ฆฌ ๋ฉ์๋์ ์ธ์๋ก ์ถ๊ฐํ ๋๊ธ ๋ชจ๋ธ์ ๋ฃ๊ฑฐ๋ ๋๊ธ์ ์์ด๋๋ฅผ ๋ฃ์ผ๋ฉด ๋๋ค.
์์ ์ด๋ ์ญ์ ๋ํ ๋ง์ฐฌ๊ฐ์ง์ด๋ค.
as ๋ณ๋ช
๋ง์ผ ๋์ฌ ๋ค์ ๋ชจ๋ธ ์ด๋ฆ์ ๋ฐ๊พธ๊ณ ์ถ๋ค๋ฉด ๊ด๊ณ ์ค์ ์ as ์ต์ ์ ์ฌ์ฉํ๋ค
// user.js
static associate(db) {
db.User.hasMany(db.Comment, { foreignKey: 'commenter', sourceKey: 'id', as: 'Answers' });
}
};
์์ ๊ฐ์ด ๊ด๊ณ๋ฅผ ์ค์ ํ๋ค๋ฉด ๋๊ธ ๊ฐ์ฒด๋ user.Answers๋ก ๋ฐ๋๋ฉฐ, ์ฟผ๋ฆฌ ๋ฉ์๋๋ค ๋ํ getAnswers() ๋ฑ์ผ๋ก ๋ณํ๋ค.
์กฐ์ธ ์์ฑ
include๋ ๊ด๊ณ ์ฟผ๋ฆฌ ๋ฉ์๋์๋ where๋ attributes ๊ฐ์ ์ต์ ๋ค์ ์ฌ์ฉํ ์ ์๋ค.
์๋๋ id๊ฐ 1์ธ ๋๊ธ๋ง ๊ฐ์ ธ์ค๊ณ , ๊ทธ ์ค์์๋ id ์ปฌ๋ผ๋ง ๊ฐ์ ธ์ค๋๋ก ํ๊ณ ์๋ค.
const user = await User.findOne({
include: [{ // left outer join
model: Comment, // joinํ ๋ชจ๋ธ
attributes: ['id'], // selectํด์ ํ์ํ ํ๋ ์ง์
where: {
id: 1, // on Comment.id = 1
},
}]
});
// ๋๋
const comments = await user.getComments({ // user๊ฐ comments๋ฅผ getํ๋ค. (user์ comments๋ ๊ด๊ณ๋์ด ์๋ค.)
attributes: ['id'], // selectํด์ ํ์ํ ํ๋ ์ง์
where: {
id: 1, // on Comment.id = 1
},
});
select users.*, comments.id
from users
inner join comments
on comments.commenter = users.id
where comments.id = 1
LIMIT 1;
์ด๋ฐ์ ์ํ๋ฆฌ์์ฆ ์ฟผ๋ฆฌ๋ฌธ
์ฟผ๋ฆฌ ๋ฌธ์์ด (literal)
์ํ๋ผ์ด์ฆ์์ ์ ๊ณตํ๋ ๋ฉ์๋๋ง์ผ๋ก๋ ์ฟผ๋ฆฌ๊ฐ ๋ถ์กฑํ ๊ฒฝ์ฐ๊ฐ ์๋ค.
literal() ์ ์ฟผ๋ฆฌ ๋ฌธ์์ด์ ์ถ๊ฐํด ์ฃผ๋ ๊ธฐ๋ฅ์ด๋ค.
User.findAll({
attributes: [
["name", "username"],
[Sequelize.literal("age + 1"), "age"],
],
})
SELECT `name` AS `username`, age + 1 AS `age` FROM `users` AS `user`
๋ณด๋๋ฐ์ ๊ฐ์ด, sql๋ฌธ์์๋ ๋ช ๋ น์ค์ ๊ทธ๋๋ก ์ฐ์ ์ฐ์ฐ์๋ฅผ ์จ์ ๊ณง๋ฐ๋ก ๊ณ์ฐ๋ ๊ฐ์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ฆด ์ ์๋๋ฐ,
์ํ๋ผ์ด์ฆ๋ ์ด๋ฌํ ๋ฆฌํฐ๋ด ์ฐ์ ์ฐ์ฐ์ ์ง์ํ์ง ์์์ literal() ๋ฉ์๋๋ฅผ ํตํด ๊ตฌํํด์ผ ํ๋ค.
SQL ์ฟผ๋ฆฌ ๊ทธ๋๋ก ์ฌ์ฉํ๊ธฐ
์ํ๋ผ์ด์ฆ์ ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ซ๊ฑฐ๋ ํท๊ฐ๋ฆฐ๋ค๋ฉด ์ง์ SQL๋ฌธ์ ํตํด ์ฟผ๋ฆฌํ ์๋ ์๋ค.
const [result, metadata] = await sequelize.query('SELECT * FROM comments');
์ฐธ๊ณ ๋ฌธํ
Node.js ๊ต๊ณผ์ - ๊ธฐ๋ณธ๋ถํฐ ํ๋ก์ ํธ ์ค์ต๊น์ง ๊ฐ์ - ์กฐํ์