SequelizeでhasManyのアソシエーションを設定する方法

準備

userが複数のbookをもつアソシエーションを設定して使ってみます。 基本的にhasOneの場合もhasManyの部分をhasOneに書き換えるだけでuserが一つのbookをもつアソシエーションとして動作します。

モデル定義

モデルにアソシエーションの設定をします。

  • hasManyの時foreignKeyでアソシエーション先(子側)のカラム名、sourceKeyでhasManyを設定した側(自分)のカラム名を設定できます
  • belongsToの時foreignKeyでアソシエーション先(親側)のカラム名、targetKeyでbelongsToを設定した側(自分)のカラム名を設定できます

    // ./model/user.js
    User.associate = function(models) {
    User.hasMany(models.Book, {foreignKey: 'userId'});
    };
    
    // ./model/book.js
    Book.associate = function(models) {
    Book.belongsTo(models.User);
    };
    

データの投入

親となるuserを一つと子となるbookを2つ入れます。

db.User.create({name: 'user-1', userId: 1})

db.Book.create({name: 'エベレストを越えて', userId: 1})
db.Book.create({name: '青春を山に賭けて', userId: 1})

User -> Book

userがhas manyで複数のbookを持っているのを確認してみます。

db.User.findOne({
    where: {
        id: 1
    },
    include: [{
        model: db.Book,
        required: false
    }]
}).then((user)=>{
    console.log(JSON.stringify(user));
    db.sequelize.close();
});

SQLクエリ

Executing (default): SELECT `User`.`id`, `User`.`name`, `User`.`createdAt`, `User`.`updatedAt`, `Books`.`id` AS `Books.id`, `Books`.`name` AS `Books.name`, `Books`.`userId` AS `Books.userId`, `Books`.`createdAt` AS `Books.createdAt`, `Books`.`updatedAt` AS `Books.updatedAt`, `Books`.`UserId` AS `Books.UserId` FROM `Users` AS `User` LEFT OUTER JOIN `Books` AS `Books` ON `User`.`id` = `Books`.`userId` WHERE `User`.`id` = 1;

出力データ

{
    "id": 1,
    "name": "name-1",
    "createdAt": "2018-03-23T15:18:49.000Z",
    "updatedAt":"2018-03-23T15:18:49.000Z",
    "Books": [{
        "id": 1,
        "name": "エベレストを越えて",
        "userId": 1,
        "createdAt": "2018-03-28T04:46:27.000Z",
        "updatedAt": "2018-03-28T04:46:27.000Z",
        "UserId":1
    },{
        "id": 2,
        "name": "青春を山に賭けて",
        "userId": 1,
        "createdAt": "2018-03-28T04:46:27.000Z",
        "updatedAt": "2018-03-28T04:46:27.000Z",
        "UserId": 1
    }]
}

Book -> User

今度は逆にbookからuserを引いてみます。

db.Book.findOne({
    where: {
        id: 1
    },
    include: [{
        model: db.User,
        required: false
    }]
}).then((book)=>{
    console.log(JSON.stringify(book));
    db.sequelize.close();
});

SQLクエリ

SELECT `Book`.`id`, `Book`.`name`, `Book`.`userId`, `Book`.`createdAt`, `Book`.`updatedAt`, `Book`.`UserId`, `User`.`id` AS `User.id`, `User`.`name` AS `User.name`, `User`.`createdAt` AS `User.createdAt`, `User`.`updatedAt` AS `User.updatedAt` FROM `Books` AS `Book` LEFT OUTER JOIN `Users` AS `User` ON `Book`.`UserId` = `User`.`id` WHERE `Book`.`id` = 1;

出力データ

{
    "id": 1,
    "name": "エベレストを越えて",
    "userId": 1,
    "createdAt": "2018-03-28T04:46:27.000Z",
    "updatedAt": "2018-03-28T04:46:27.000Z",
    "UserId": 1,
    "User": {
        "id": 1,
        "name": "name-1",
        "createdAt": "2018-03-23T15:18:49.000Z",
        "updatedAt": "2018-03-23T15:18:49.000Z"
    }
}