Cannot associate tables in sequalize (node js + sequalize) - node.js

I've got two tables that are structured like this:
FeedPost
id, text, likecount, commentcount
Comment
id, text, lkpfeedpostid
So there's a foreign key from comment to feedpost via lkpfeedpostid. So one FeedPost could have many Comment. I'm trying to set this up in sequalize so that when I do a FeedPost.findAll(), it pulls back the feed posts with all the comments.
Here's how I've set it up:
Model Definitions:
FeedPost:
module.exports = function(sequelize, DataTypes) {
return sequelize.define('FeedPost', {
...
...
}, {
tableName: 'FeedPost',
classMethods: {
associate : function(models) {
FeedPost.hasMany( Comment, { as: 'comments' });
},
},
});
};
Comment:
module.exports = function(sequelize, DataTypes) {
return sequelize.define('Comment', {
...
...
}, {
tableName: 'Comment',
classMethods: {
associate : function(models) {
Comment.belongsTo(FeedPost, { foreignKey: 'lkpfeedpostid'})
},
},
});
};
I'm importing them like:
const FeedPost = sequelize.import('../models/FeedPost');
const Comment = sequelize.import('../models/Comment');
And passing them into an express router like:
app.use(feed(FeedPost, Comment));
module.exports = (FeedPost, Comment) => {
const api = Router();
api.get('/api/feed', (req, res) => {
FeedPost.findAll( { include: [ {model: Comment, as: 'Comment' }]}).then(results => {
res.json({results});
});
}
I've tried tons of variations of this found in these links:
http://docs.sequelizejs.com/manual/tutorial/models-definition.html#import
http://docs.sequelizejs.com/class/lib/associations/has-many.js~HasMany.html
https://github.com/sequelize/sequelize/issues/3273
And whenever I hit the route, I keep getting the error that says
Unhandled rejection SequelizeEagerLoadingError: Comment is not associated to Feed!

I am going with that assumption that your sequelize version >=4.
classMethods and instanceMethods have been removed. The changelog can be found here : Sequelize V4 Breaking Changes
From their docs you can refer the current method to specify associations.
FeedPost
module.exports = function(sequelize, DataTypes) {
const FeedPost = sequelize.define('FeedPost', {/*Attributes here*/});
FeedPost.hasMany(Comment, { as: 'comments' })
};
Comment
module.exports = function(sequelize, DataTypes) {
const Comment = sequelize.define('Comment', {/*Attributes here*/});
Comment.BelongsTo(Comment, { foreignKey: 'lkpfeedpostid', targetKey: 'id' })
};
The following query should work:
FeedPost.findAll( { include: [ {model: Comment, as: 'comments' }]})

Related

Sequelize error: "Association with alias "sender" does not exist on GlobalMessage"

I'm building a Node/Express app with Sequelize. I created some models and made some database migrations with sequelize-cli with minimal difficulty and decided to add some associations between my entities by adding them to the model files and calling sequelize.sync(). Everything seemed to go smoothly until I made a query to test the associations and I got this error: Association with alias "sender" does not exist on GlobalMessage. Below is the related code:
models/globalmessage.js:
'use strict';
module.exports = (sequelize, DataTypes) => {
const GlobalMessage = sequelize.define('GlobalMessage', {
body: DataTypes.TEXT,
timestamp: DataTypes.DATE,
SenderId: {
type: DataTypes.INTEGER,
references: {
model: "Users",
key: "id"
}
}
}, {});
GlobalMessage.associate = function(models) {
// associations can be defined here
GlobalMessage.belongsTo(models.User, {foreignKey: 'SenderId', as: 'sender'});
};
return GlobalMessage;
};
models/user.js:
'use strict';
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
email: DataTypes.STRING,
password: DataTypes.STRING,
username: DataTypes.STRING
}, {});
User.associate = function(models) {
// associations can be defined here
User.hasMany(models.GlobalMessage, {
as: 'globalMessages'
})
};
return User;
};
routes/api/user.js:
const Sequelize = require("sequelize");
const express = require("express");
const bcrypt = require('bcrypt');
const saltRounds = 10;
const router = express.Router();
const db = require("../../db/index");
const UserModel = require("../../models/user");
const User = UserModel(db, Sequelize);
const GlobalMessageModel = require("../../models/globalmessage")
const GlobalMessage = GlobalMessageModel(db, Sequelize);
router.post("/findOne", function (request, response, next) {
GlobalMessage.findOne({
where: {body: 'Body of message 1'}, include: 'senders'
})
.then((foundUser) => {
response.json(foundUser)
})
.catch((err) => {
console.log("Error while finding user: ", err)
})
})
module.exports = router;
I get the error when I send a request to localhost/api/user/findOne. I've searched all over and have found little documentation about this specific error and any advice I've found hasn't proven to be fruitful to me. Any help would be appreciated!

one-to-many relationships in sequelizer

Been looking at various answers and git issues and still can't get it to work. I have drivers model and CarDrivers model. A driver can drive multiple cars so I want to create a one-to-many relationships.
Drivers Model is (models/drivers.js):
'use strict';
module.exports = (sequelize, DataTypes) => {
const Driver = sequelize.define('Driver', {
name: DataTypes.STRING
}, {});
Driver.associate = function(models) {
// associations can be defined here
};
return Driver;
};
now CarDrivers (models/cardrivers.js):
'use strict';
module.exports = (sequelize, DataTypes) => {
const CarDriver = sequelize.define('CarDriver', {
status: DataTypes.INTEGER,
}, {});
CarDriver.associate = function(models) {
// associations can be defined here
CarDriver.belongsTo(models.Driver, {
onDelete: "CASCADE",
foreignKey: 'id',
as: 'car_driver'
});
};
return CarDriver;
};
Data migration works with no errors but I don't see an entry/related column in table CarDrivers. Anybody can help fix it please.
The issue with your code is that the foreign_key in your association definition cannot be id, as that will clash with the id of the CarDriver table. If you change it to driver_id, you will see that column in the car_driver table:
const Driver = sequelize.define('driver', {
name: { type: Sequelize.STRING }
});
const CarDriver = sequelize.define('car_driver', {
name: { type: Sequelize.STRING }
});
CarDriver.belongsTo(Driver, {
onDelete: 'CASCADE',
foreignKey: 'driver_id'
});
const driver = await Driver.create({
name: 'first driver'
})
const carDriver = await CarDriver.create({
name: 'first carDriver',
driver_id: driver.id
})
Two notes:
foreignKey is optional. If you leave it blank, Sequelize will default to camelcase, e.g. driverId
Your migration file must account for the foreign key on the CarDriver table:
up: function(queryInterface, Sequelize) {
return queryInterface.createTable('car_driver', {
id: {},
driver_id: {
..
}
});
}

A is not associated to B

Looked on the internet about similar questions/errors, none of them helped me...
Unhandled rejection SequelizeEagerLoadingError: Task is not associated to User!
My users route
router.get('', function (req, res) {
models.User.findAll({
include: [
{
model: models.Task,
as: 'tasks'
}
]
}).then(function (users) {
res.send(users);
});
});
User model
'use strict';
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
first_name: DataTypes.STRING,
last_name: DataTypes.STRING,
email: DataTypes.STRING
}, {
underscored: true
});
User.associations = function (models) {
User.hasMany(models.Task, { as: 'tasks' });
};
return User;
};
Task model
'use strict';
module.exports = (sequelize, DataTypes) => {
const Task = sequelize.define('Task', {
name: DataTypes.STRING
}, {
underscored: true
});
Task.associations = function (models) {
Task.belongsTo(models.User);
};
return Task;
};
I associate them both, and made a bidirectional relationship..
As you are using the finder function for association with as option, Sequelize cannot find that alias, as it is not defined explicitly anywhere. Please try this one:
User.associations = function (models) {
User.hasMany(models.Task, { as: 'tasks' });
};
Hope this helps.

Sequelizer connecting multiple hasMany associations

I am following the offical Sequelizer docs, but I am unable to get it working with multiple "hasMany" associations.
The below code renders an error:
Unhandled rejection Error: [object Object] is not associated to User!
How is this done correctly?
models/user.js
module.exports = function(sequelize, DataTypes) {
var User = sequelize.define("User", {
username: DataTypes.STRING
}, {
classMethods: {
associate: function(models) {
User.hasMany(models.Movie, models.Book)
}
}
});
return User;
};
routes/index.js
var models = require('../models');
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
models.User.findAll({
include: [ models.Task, models.Movie ]
}).then(function(users) {
res.render('index', {
title: 'Sequelize: Express Example',
users: users
});
});
});
module.exports = router;
Found the issue, you have to define them individually (eg User.hasMany twice)
module.exports = function(sequelize, DataTypes) {
var User = sequelize.define("User", {
username: DataTypes.STRING
}, {
classMethods: {
associate: function(models) {
User.hasMany(models.Movie),
User.hasMany(models.Books)
}
}
});
return User;
};

Sequelize belongstomany associations : create a post and associate its existing tags

I got two models associates by belongsToMany associations.
Posts.js :
'use strict';
module.exports = function(sequelize, DataTypes) {
var Posts = sequelize.define('Posts', {
title: DataTypes.STRING,
body: DataTypes.STRING
}, {
classMethods: {
associate: function(models) {
Posts.belongsToMany(models.Tags, {
through: 'PostsTags',
as:'posts_has_tags',
foreignKey:'postId'
});
}
}
});
return Posts;
};
and Tags.js :
'use strict';
module.exports = function(sequelize, DataTypes) {
var Tags = sequelize.define('Tags', {
name: DataTypes.STRING
},{
classMethods: {
associate: function(models) {
Tags.belongsToMany(models.Posts, {
through: 'PostsTags',
as:'posts_has_tags',
foreignKey:'tagId'
});
}
}
});
return Tags;
};
In my db i got 2 existing tags. (id:1 and id:2)
I got trouble when i create a Post i want to associate it to one of these tags.
By running this code :
create: function(request, reply){
let post = Object.assign({}, request.payload, request.params);
models.Posts.create({
title: post.title,
body: post.body,
posts_has_tags: [{tagId:1}]
},{
include: [{model:models.Tags, as:'posts_has_tags'}]
}).then(function(newPost){
if(!newPost){
return reply('[404] Not found').code(404);
}
reply(newPost).code(200);
})
}
it runs this query :
INSERT INTO `Posts` (`id`,`title`,`body`,`createdAt`,`updatedAt`) VALUES (DEFAULT,'TITLE 1','BODY 1','2017-02-05 18:33:21','2017-02-05 18:33:21');
Executing (default): INSERT INTO `Tags` (`id`,`createdAt`,`updatedAt`) VALUES (DEFAULT,'2017-02-05 18:33:21','2017-02-05 18:33:21');
Executing (default): INSERT INTO `PostsTags` (`createdAt`,`updatedAt`,`postId`,`tagId`) VALUES ('2017-02-05 18:33:21','2017-02-05 18:33:21',70,20);
It creates a new post but also a new Tag that i don't want.
It creates the associations in poststags table but with the bad tag id (the one just created instead of the id 1)
In the promise how can i access to the setAssociation() or addAssocation() method sequelize is supposed to create on belongsToMany associations :
I got errors or undefined if i try newPost.addTags or newPost.setTags, or models.Posts.addTags or models.Posts.setTags
If anybody can help me, he's welcome.
I stuck on this for days and i'd like to understand right how i can use sequelize the best way.
I changed the alias "as" for both models :
Posts.js :
'use strict';
module.exports = function(sequelize, DataTypes) {
var Posts = sequelize.define('Posts', {
title: DataTypes.STRING,
body: DataTypes.STRING
}, {
classMethods: {
associate: function(models) {
Posts.belongsToMany(models.Tags, {
through: 'PostsTags',
as:'postHasTags',
foreignKey:'postId'
});
}
}
});
return Posts;
};
Tags.js :
'use strict';
module.exports = function(sequelize, DataTypes) {
var Tags = sequelize.define('Tags', {
name: DataTypes.STRING
},{
classMethods: {
associate: function(models) {
Tags.belongsToMany(models.Posts, {
through: 'PostsTags',
as:'tagHasPosts',
foreignKey:'tagId'
});
}
}
});
return Tags;
};
Both alias are reversed.
When i create a new post or update one, i can access to the setter built by sequelize (model.setAssociation) in the promise :
upsert: function(request, reply){
let receivedPost = Object.assign({}, request.payload, request.params);
models.Posts.find({
where:{ id:receivedPost.id }
}).then(post => {
if(post){
post.setPostHasTags(receivedPost.tags)
reply(post).code(200)
} else {
models.Posts.create({
title: receivedPost.title,
body: receivedPost.body
}).then(newPost => {
newPost.setPostHasTags(receivedPost.tags)
reply(newPost).code(200);
});
}
});

Resources