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
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!
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: {
..
}
});
}
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.
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;
};
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);
});
}
});