Question

I really love Sequelize so far but there's something I just can't seem to wrap my head around and get set up properly. I understand database schemas and how to write SQL but there's something about this ORM that I'm just not understanding when it comes to this type of relationship.

Two objects/tables in my model need a one-to-one relationship as well as a one-to-many. Here's how I would describe it...

User

  • has many Media (should create FK on Media table as UserId)
  • has one Media called PrimaryMedia (should create FK on User table as PrimaryMediaId)

I've read the documents a couple of times and tried different permutations in order to get the tables creating the right way but then I don't understand what to expect from my objects in terms of the setters/getters. I.E., for the example above I would expect that...

User

  • has methods addMedia, removeMedia and setMedia
  • has method setPrimaryMedia

What would be the proper way to set up these two model objects?

EDIT: I've managed to get the one-to-one working entirely but the one-to-many isn't updating the foreign key...

User.js

...
User.hasMany(models.Media, {
    as: 'Media',
    foreignKeyConstraint: true
}),
User.hasOne(models.Media, {
    as: 'PrimaryMedia'
}),
User.belongsTo(models.Media, {
    as: 'PrimaryMedia',
    foreignKey: 'PrimaryMediaId'
})
...

Media.js

...
Media.hasOne(models.User, {
    as: 'User',
    foreignKey: 'PrimaryMediaId'
}),
...

In action...

Media.create({
    type: 'image',
    nativeURL: nativeURL,
    mediumURL: mediumURL,
    smallURL: smallURL
}).success(function(newMedia) {
    _user.addMedium(newMedia).success(function(){  // THIS ISN'T WORKING (Media.UserId column always null)
        console.log('media user set');
    });
    _user.setPrimaryMedia(newMedia).success(function(){ // THIS IS WORKING
        console.log('user primary media set');
    });
    success(newMedia);
}).error(function(err) {
    error(err);
});
Was it helpful?

Solution

Maybe add property 'primary' to Media, and use as:

user.addMedium(newMedia, { primary: true });

I run your code, its' working:

var sequelize = new Sequelize('schema', 'user', 'password', {host: 'localhost'});

User = sequelize.define('User', {name: Sequelize.STRING});

Media  = sequelize.define('Media', {title: Sequelize.STRING});

User.hasMany(Media, {
    as: 'Media',
    foreignKeyConstraint: true
}),

User.hasOne(Media, {
    as: 'PrimaryMedia'
}),

User.belongsTo(Media, {
    as: 'PrimaryMedia',
    foreignKey: 'PrimaryMediaId'
});

sequelize.sync().success(function(){

    User.create().success(function(_user){

        Media.create({}).success(function(newMedia) {

            _user.addMedium(newMedia).success(function(){  // THIS ISN'T WORKING (Media.UserId column always null)
                console.log('media user set');
            }).error(function(error){
                console.log('cant add media', error);
            });

            _user.setPrimaryMedia(newMedia).success(function(){ // THIS IS WORKING
                console.log('user primary media set');
            }).error(function(error){
                console.log('cant set primaryMedia', error);
            });

        }).error(function(err) {
            error(err);
        });

    }).error(function(error){
        console.log('user create', error)
    })

}).error(function(error){
    console.log('sync error', error);
});

log:

INSERT INTO `Users` (`id`,`createdAt`,`updatedAt`) VALUES (DEFAULT,'2014-02-24 13:01:57','2014-02-24 13:01:57');
INSERT INTO `Media` (`id`,`createdAt`,`updatedAt`) VALUES (DEFAULT,'2014-02-24 13:01:57','2014-02-24 13:01:57');
SELECT * FROM `Media` WHERE `UserId` = 1 AND `Media`.`id` = 1;
UPDATE `Users` SET `PrimaryMediaId`=1,`updatedAt`='2014-02-24 13:01:57' WHERE `id`=1
user primary media set
UPDATE `Media` SET `id`=1,`createdAt`='2014-02-24 13:01:57',`updatedAt`='2014-02-24 13:01:57',`UserId`=1 WHERE `id`=1
media user set
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top