sequelize는 models나 migration이나 쿼리함수들 검색을 해봐도
왜 다 클래스 형태나 파일구조가 제각각인 글들이 나오는지 모르겠다.
그래서 그중에 뭘 적용해야 맞는지를 모르겠다.
그래서 모델, 마이그래이션 쓰기 귀찮아서 워크벤치로 관리해줬었는데
쿼리함수는 모델객체들을 보고 실행되기에 대충 작성할 수도 없었다.
그리고 JOIN쿼리를 하기 위해서 그 모델객체들의 1:N 관계나 외래키 등의 관계를 제대로 적용하려면 마이그레이션도 결국엔 제대로 써야했다.
그래서 오래오래 찾다가 결국에 외래키 관계 작성하는 법을 알아냈다.
npx sequelize model:generate --name User --attributes email:string,nickname:string,password:string
이런식으로 테이블 속성들 처음부터 다 넣어준다음에 나중에 모델에 내손으로 외래키 내용 추가하려면 귀찮으니까
일단 기본적인 속성만 몇개 적어서 테이블을 만들었다. 그리고 그 후에 마이그레이션으로 참조 관계를 자세하게 작성한 속성을 추가하기로 했다.
await queryInterface.addColumn(
'like',
'fk_note_id',
{
type: Sequelize.INTEGER,
references: {
model: 'note',
key: "noteid"
}
}
);
이게 마이그레이션 파일의 컬럼을 추가하는 함수 부분이다.
like라는 테이블에 fk_note_id라는 컬럼을 추가하는데 그거의 타입은 integer이고
참조는 note라는 모델(테이블)을 참조하는데 note테이블의 noteid를 참조한다.
이렇게 마이그레이션을 작성해준다고 끝이 아니다.
models안에서도 뭔가를 해야하는데 삽질한 과정까지 써보자면,
fk_note_id: {
type: DataTypes.INTEGER,
},
like 모델의 fk_note_id에 외래키를 써줘야할거같지만 외래키관계 만드는데 성공한 후에도 여기는 그냥 이거만 써져있다. 여기가 아니다.
static associate(models) {
Like.belongsTo(models.User);
Like.belongsTo(models.note);
}
그러면 like 모델 클래스 안의 저 associate 함수 안에 associate라는 이름답게 다른 모델과의 관계성을 적어놓으면 될거같지만 이거도 아니다.
여기 적어도 소용이 없었다.
답은 models의 index.js에 명시하는 것이었다.
db.User = require('./user.js')(sequelize, Sequelize);
db.Note = require('./note.js')(sequelize, Sequelize);
db.Comment = require('./comment.js')(sequelize, Sequelize);
db.Like = require('./like.js')(sequelize, Sequelize);
db.Note.hasMany(db.Like);
db.Like.belongsTo(db.Note, {
foreignKey: "fk_note_id"
});
db.User.hasMany(db.Like, { as: "L" });
db.Like.belongsTo(db.User, {
foreignKey: "fk_user_id",
as: "userid"
});
일단 모델들을 다 임포트 해주고
그 모델들 관의 관계를 저렇게 적어준다.
1:N 관계인거 중에 1이거를 A N인거를 B라고 하면
A.hasMany(B);
B.belongsTo(A, {~}
이런식으로 둘의 관계를 작성하고 {}안에 like의 fk_note_id가 포린키임을 명시한다.
이렇게 작성하니까 드디어 join 쿼리가 작동했다.
const LIKENOTES = await Like.findAll({ //좋아요 한게 없으면 []
include : [{
model:Note,
attributes:['title', 'content', 'createdAt', 'updatedAt', 'like'],
}],
attributes:['fk_user_id', 'fk_note_id'],
raw:true //raw값이 true이면 dataValues부분만 리턴.
});
join 쿼리는 이런식으로 작성했다.
사실 위의 migration이나 models부분이나 이 쿼리문에서나 별명을 붙일 수 있는 문법들이 있었는데
예를들면 Not as N 이런거
이런 기능들을 쓰니까 또 뭔가 에러가 나서 빼버렸다.
아무튼 조인의 역할을 하는건 include라는 저 구문이고.
밖에 있는게 꼭 N이나 1이거나하는 조건은 없고 둘이 참조관계만 되어있으면 된다.
findAll()
const comment = await Comment.findAll({
order : [
['createdAt', 'desc']
],
where: {
fk_note_id : commentDto.noteid
}
});
findOne()
findByPk()
const author = await Comment.findByPk(req.params.commentid);
create()
const comment = await Comment.create({
fk_note_id : commentDto.noteid,
fk_user_id : commentDto.userid,
content : commentDto.content
}
update()
const comment = await Comment.update({
content : commentDto.content
}, {
where : {
commentid : commentDto.commentid
}
}
)
리턴값 : affectedRows를 리턴하는 것 같다. [1]이 리턴되면 테이블의 1행이 영향받았단 것이므로 성공. [0]이나 [2]나 기타 등등이라면 실패.
destroy()
리턴값 : 이것도 affectedRows 를 리턴하는 듯한데, update랑은 다르게 []로 감싸져있지않다. 성공하면 1, 실패하면 0이나 기타를 리턴하는 듯.
아니면 이거는 true/false 의미로 1/0을 리턴하는 것일지도 모르겠다.
const comment = await Comment.destroy({
where : {
commentid : commentDto.commentid
}
}
)
increment() //기존 값을 지정한 숫자만큼 증가
마이그레이션 관련
https://crispypotato.tistory.com/156
https://any-ting.tistory.com/54
쿼리 관련
https://guiyomi.tistory.com/87
https://extbrain.tistory.com/47
https://includecoding.tistory.com/217
외래키 설정 관련
https://falsy.me/sequelize-2-%EC%BF%BC%EB%A6%AC-%EC%99%B8%EB%9E%98%ED%82%A4-for-mysql/
https://github.com/boostcamp-2020/IssueTracker-13/wiki/Sequelize-CLI-%26-Migration-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0
https://kyounghwan01.github.io/blog/etc/sequelize/sequelize-join/#include