sequelize ORM을 사용하고 있습니다. 모든 것이 훌륭하고 깨끗하지만 join
쿼리 와 함께 사용할 때 문제가 발생했습니다 . 사용자와 게시물의 두 가지 모델이 있습니다.
var User = db.seq.define('User',{
username: { type: db.Sequelize.STRING},
email: { type: db.Sequelize.STRING},
password: { type: db.Sequelize.STRING},
sex : { type: db.Sequelize.INTEGER},
day_birth: { type: db.Sequelize.INTEGER},
month_birth: { type: db.Sequelize.INTEGER},
year_birth: { type: db.Sequelize.INTEGER}
});
User.sync().success(function(){
console.log("table created")
}).error(function(error){
console.log(err);
})
var Post = db.seq.define("Post",{
body: { type: db.Sequelize.TEXT },
user_id: { type: db.Sequelize.INTEGER},
likes: { type: db.Sequelize.INTEGER, defaultValue: 0 },
});
Post.sync().success(function(){
console.log("table created")
}).error(function(error){
console.log(err);
})
나는 그것을 만든 사용자의 정보가 담긴 게시물로 응답하는 쿼리를 원합니다. 원시 쿼리에서 다음을 얻습니다.
db.seq.query('SELECT * FROM posts, users WHERE posts.user_id = users.id ').success(function(rows){
res.json(rows);
});
내 질문은 SQL 쿼리 대신 ORM 스타일을 사용하도록 코드를 어떻게 변경할 수 있습니까?
답변
User.hasMany(Post, {foreignKey: 'user_id'})
Post.belongsTo(User, {foreignKey: 'user_id'})
Post.find({ where: { ...}, include: [User]})
당신에게 줄 것입니다
SELECT
`posts`.*,
`users`.`username` AS `users.username`, `users`.`email` AS `users.email`,
`users`.`password` AS `users.password`, `users`.`sex` AS `users.sex`,
`users`.`day_birth` AS `users.day_birth`,
`users`.`month_birth` AS `users.month_birth`,
`users`.`year_birth` AS `users.year_birth`, `users`.`id` AS `users.id`,
`users`.`createdAt` AS `users.createdAt`,
`users`.`updatedAt` AS `users.updatedAt`
FROM `posts`
LEFT OUTER JOIN `users` AS `users` ON `users`.`id` = `posts`.`user_id`;
위의 쿼리는 게시 한 내용에 비해 약간 복잡해 보일 수 있지만 기본적으로 사용자 테이블의 모든 열에 별칭을 지정하여 반환 될 때 올바른 모델에 배치되고 posts 모델과 혼합되지 않도록하는 것입니다.
그 외에는 두 테이블에서 선택하는 대신 JOIN을 수행하지만 결과는 동일해야합니다.
추가 읽기 :
답변
받아 들여진 대답은 기술적으로 틀린 것은 아니지만 원래 질문에 대한 대답도 아니고 댓글에있는 후속 질문에도 대답하지 않았습니다. 그러나 나는 그것을 알아 냈습니다.
사용자가있는 모든 게시물 (및 사용자가있는 게시물 만)을 찾으려면 SQL이 다음과 같이 표시됩니다.
SELECT * FROM posts INNER JOIN users ON posts.user_id = users.id
OP의 원래 SQL과 의미 상 동일합니다.
SELECT * FROM posts, users WHERE posts.user_id = users.id
그러면 이것이 당신이 원하는 것입니다.
Posts.findAll({
include: [{
model: User,
required: true
}]
}).then(posts => {
/* ... */
});
true로 설정해야 내부 조인을 생성 할 수 있습니다. 왼쪽 외부 조인 (사용자가 연결되어 있는지 여부에 관계없이 모든 게시물을 가져 오는 위치)을 원하면 required를 false로 변경하거나 기본값이므로 해제 상태로 둡니다.
Posts.findAll({
include: [{
model: User,
// required: false
}]
}).then(posts => {
/* ... */
});
출생 연도가 1984 년인 사용자의 모든 게시물을 찾으려면 다음을 원할 것입니다.
Posts.findAll({
include: [{
model: User,
where: {year_birth: 1984}
}]
}).then(posts => {
/* ... */
});
where 절을 추가하자마자 required는 기본적으로 true입니다.
첨부 된 사용자가 있는지 여부에 관계없이 모든 게시물을 원하지만 사용자가있는 경우 1984 년에 태어난 사용자 만있는 경우 필수 필드를 다시 추가합니다.
Posts.findAll({
include: [{
model: User,
where: {year_birth: 1984}
required: false,
}]
}).then(posts => {
/* ... */
});
이름이 “Sunshine”인 모든 게시물을 원하고 1984 년에 태어난 사용자의 경우에만 다음과 같이하면됩니다.
Posts.findAll({
where: {name: "Sunshine"},
include: [{
model: User,
where: {year_birth: 1984}
}]
}).then(posts => {
/* ... */
});
이름이 “Sunshine”인 모든 게시물을 원하고 게시물의 post_year 속성과 일치하는 동일한 연도에 태어난 사용자에게 속한 경우에만 다음을 수행합니다.
Posts.findAll({
where: {name: "Sunshine"},
include: [{
model: User,
where: ["year_birth = post_year"]
}]
}).then(posts => {
/* ... */
});
누군가가 자신이 태어난 해에 게시물을 올릴 것이라는 것은 말이 안되지만 이것은 단지 예일뿐입니다. 🙂
나는이 문서에서 (대부분) 이것을 알아 냈습니다.
답변
Model1.belongsTo(Model2, { as: 'alias' })
Model1.findAll({include: [{model: Model2 , as: 'alias' }]},{raw: true}).success(onSuccess).error(onError);
답변
제 경우에는 다음과 같이했습니다. UserMaster에서 userId 는 PK이고 UserAccess에서 userId 는 UserMaster의 FK입니다.
UserAccess.belongsTo(UserMaster,{foreignKey: 'userId'});
UserMaster.hasMany(UserAccess,{foreignKey : 'userId'});
var userData = await UserMaster.findAll({include: [UserAccess]});