I still trying to get menu_title from associated Menu model to json. If I use below described code console shows me error
ER_BAD_FIELD_ERROR: Unknown column 'Products.MenuId' in 'field list' also if I have defined {foreignKey: 'menu_id'}. What I'm doing wrong?
Menu model:
module.exports = function(sequelize, Sequelize) {
var Menu = sequelize.define("Menu", {
owner_id: Sequelize.INTEGER,
menu_title: Sequelize.STRING,
}, {
classMethods: {
associate: function(models) {
Menu.hasMany(models.Product)
}
}
});
return Menu;
};
Product model:
module.exports = function(sequelize, Sequelize) {
var Product = sequelize.define("Product", {
owner_id: Sequelize.INTEGER,
menu_id: Sequelize.INTEGER,
product_title: Sequelize.STRING,
}, {
classMethods: {
associate: function(models) {
Product.belongsTo(models.Menu, { foreignKey: 'menu_id'})
}
}
});
return Product;
};
Then inside controller:
Menu.find({
where: { owner_id: req.user.id },
include: [
{ model: Product }
]
}).success(function(match) {
res.json(match.home);
});
Thanks for any help!
You need to include the foreign key on both sides of the relation
Menu.hasMany(models.Product, { foreignKey: 'menu_id'})
Otherwise sequelize assumes that the foreign key is called menuId when querying from the menu side of the relation
Related
I have 3 models
module.exports = (sequelize, DataTypes) => {
class User extends Model {
static associate({ Chat, Message }) {
this.belongsToMany(Chat, {
through: 'UsersChats',
foreignKey: 'userId',
as: 'chats'
});
this.hasMany(Message, { as: 'messages', foreignKey: 'userId' });
}
}
User.init(
{
login: {
type: DataTypes.STRING,
allowNull: false,
unique: true
},
password: {
type: DataTypes.STRING,
allowNull: false
}
},
{
sequelize,
modelName: 'User'
}
);
return User;
};
module.exports = (sequelize, DataTypes) => {
class Chat extends Model {
static associate({ Message, User }) {
this.hasMany(Message, { as: 'messages', foreignKey: 'chatId' });
this.belongsToMany(User, {
through: 'UsersChats',
foreignKey: 'chatId',
as: 'users'
});
}
}
Chat.init(
{
name: DataTypes.STRING
},
{
sequelize,
modelName: 'Chat'
}
);
return Chat;
};
module.exports = (sequelize, DataTypes) => {
class Message extends Model {
static associate({ Chat, User }) {
this.belongsTo(Chat, { foreignKey: 'chatId', as: 'chat' });
this.belongsTo(User, { foreignKey: 'userId', as: 'user' });
}
}
Message.init(
{
userId: DataTypes.UUID,
text: DataTypes.TEXT,
chatId: DataTypes.UUID
},
{
sequelize,
modelName: 'Message'
}
);
return Message;
};
I'm trying to build a query like this for getting a list of chats, ordered by creation and limited by a last message
select C.name,
C.id,
M.text,
M."userId"
from "Chats" as C
left join lateral (
select text,
"userId",
"createdAt"
from "Messages" M
where M."chatId" = C.id
order by "createdAt" DESC
limit 1
) M on true
order by M."createdAt" DESC;
Sequelize query
Chat.findAll({
include: [
{
model: User,
as: 'users',
through: {
where: {
id: userId
}
}
},
{
model: Message,
as: 'messages',
limit: 1,
order: [['createdAt', 'DESC']]
}
],
order: [['messages', 'createdAt', 'DESC']]
});
But when Execute a query, I got an exception
SELECT "Chat"."id", "Chat"."name", "Chat"."createdAt", "Chat"."updatedAt", "users"."id" AS "users.id", "users"."login" AS "users.login", "users"."password" AS "users.password", "users"."createdAt" AS "users.createdAt", "users"."updatedAt" AS "users.updatedAt", "users->UsersChats"."createdAt" AS "users.UsersChats.createdAt", "users->UsersChats"."updatedAt" AS "users.UsersChats.updatedAt", "users->UsersChats"."chatId" AS "users.UsersChats.chatId", "users->UsersChats"."userId" AS "users.UsersChats.userId" FROM "Chats" AS "Chat" LEFT OUTER JOIN ( "UsersChats" AS "users->UsersChats" INNER JOIN "Users" AS "users" ON "users"."id" = "users->UsersChats"."userId" AND "users->UsersChats"."id" = 'a529cfbd-4104-4ed8-b135-443de9d3b41a') ON "Chat"."id" = "users->UsersChats"."chatId" ORDER BY "messages"."createdAt" DESC;
DatabaseError [SequelizeDatabaseError]: missing FROM-clause entry for table "messages"
I know, that the issue in this order: [['messages', 'createdAt', 'DESC']], but I need order by last messages. What can I do, any ideas?
Given a table Show and a table Venue, with the below associations:
Show.belongsTo(Venue, { foreignKey: { name: 'id_venue', allowNull: false } });
Venue.hasMany(Show);
I'm trying to grab one venue and all of its associated shows.
const getSingleVenue = async (req, res) => {
try {
const { venueName } = req.params;
const venue = await Venue.findOne({
where: {
name: venueName,
},
include: [
{ model: Show }
]
})
res.send(venue);
}
catch(err) {
console.log(err);
res.send(400);
}
}
Right now, I'm stuck on the error Unknown column 'show.venueId' in 'field list'.
Not sure how to edit my associations to give sequelize what it's looking for.
The problem is this Venue.hasMany(Show); Y're not defined the foreign key.
Replace some code :
Show.belongsTo(Venue, { foreignKey: { name: 'id_venue', allowNull:
false } }); Venue.hasMany(Show);
By
Show.belongsTo(Venue, { foreignKey: { name: 'id_venue', allowNull: false } });
Venue.hasMany(Show, { foreignKey: { name: 'id_venue', as: shows } };
How to properly use nested include query with sequelize(nodejs)
my nested include query with sequelize is giving me this error
"category is associated to course using an alias. You've included an alias (Category), but it does not match the alias defined in your association."
what i want is from the users list, i want to get all the tcourses, then from that, i will get all the courses then from that i want to get the list of all the categories
I don't know what I did that is wrong, I just need it to work, am still new to nodejs
here is the code
export default {
Query: {
users: combineResolvers(isAdmin, async (parent, args, { models }) => {
return await models.User.findAll();
}),
},
User: {
messages: async (user, args, { models }) => {
return await models.Message.findAll({
where: { userId: user.id },
});
},
tcourses: async (user, args, { models }) => {
return await models.TCourses.findAll({
where: { UserId: user.id },
include: [{model: models.Course, as: 'Course', include: [{model: models.Category, as: 'Category'}]}]
})
}
},
}
here is my tcourses model code
const tcourses = (sequelize, DataTypes) => {
const TCourses = sequelize.define('tcourses', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
unique: true,
primaryKey: true,
field: 'id'
},
}, {
timestamps: false
});
TCourses.associate = models => {
TCourses.belongsTo(models.Course,{ as: 'Course', required: false})
TCourses.belongsTo(models.User,{ as: 'User'})
};
return TCourses;
};
export default tcourses;
here is my Course model code
const course = (sequelize, DataTypes) => {
const Course = sequelize.define('course', {
Title: {
type: DataTypes.STRING,
validate: {
notEmpty: {
args: true,
msg: 'Enter Course Title'
}
},
},
}, {
timestamps: false
})
Course.associate = models => {
Course.belongsTo(models.Category, { as: 'Cat'})
Course.hasMany(models.Requirements,{onDelete: 'CASCADE', foreignKey: 'CourseId'})
Course.belongsTo(models.User, { as: 'Owners'})
Course.hasMany(models.Audience,{onDelete: 'CASCADE', foreignKey: 'CourseId'})
Course.hasMany(models.TCourses,{onDelete: 'CASCADE', foreignKey: 'CourseId'})
};
return Course
};
export default course
here is my Category model code
const category = (sequelize, DataTypes) => {
const Category = sequelize.define('category', {
catName: {
type: DataTypes.STRING,
validate: {
notEmpty: {
args: true,
msg: 'Enter Category name'
}
},
},
}, {
timestamps: false
});
Category.associate = models => {
Category.hasMany(models.Course,{onDelete: 'CASCADE', foreignKey: 'CatId'})
Category.hasMany(models.TCategory,{onDelete: 'CASCADE', foreignKey: 'CategoryId'})
};
return Category;
};
export default category;
pls how can i make it to work
You have to provide the same alias for model in both include statement and while defining association.
The error also specifies the same,
"category is associated to course using an alias. You've included an alias (Category), but it does not match the alias defined in your association."
While querying the DB you have specified the alias for category table as Category
models.TCourses.findAll({
where: { UserId: user.id },
include: [{model: models.Course, as: 'Course', include: [{model: models.Category, as: 'Category'}]}]
})
In the Course model you have defined the association as Cat
Course.belongsTo(models.Category, { as: 'Cat'})
Now you have to make it same, i,e use either Cat or Catgory at both the places.
I have three basic tables A, B and C. A and B have many-to-many relation. So I use junction table of A_B. C has one-to-many relation to A_B. This is how they are defined when using sequelize.
A.associate = function(models) {
A.belongsToMany(models.B, {
through: 'A_B',
as: 'Bs',
foreignKey: 'a_id'
});
};
B is similar, then C.
C.associate = function(models) {
C.hasMany(models.A_B, {
as: 'ABs',
foreignKey: 'c_id'
});
};
But when I run it, I get the following message.
Error: C.hasMany called with something that's not a subclass of Sequelize.Model
It looks like sequelize does not recognize A_B as valid. Any way to solve?
Thanks.
If you want to fetch lines of the A_B table, then you need to create a model representing it (it won't be "created" in sequelize when you declare the association in A with through).
Assumptions :
your table A_B has three columns a_id, b_id and c_id
The code should look something like :
const A = sequelize.define('A', {
id: Sequelize.STRING
})
A.associate = function(models) {
A.belongsToMany(models.B, {
through: {
model: 'A_B',
},
as: 'Bs',
foreignKey: 'a_id',
otherKey: 'b_id'
});
}
const B = sequelize.define('B', {
id: Sequelize.STRING
})
B.associate = function(models) {
B.belongsToMany(models.A, {
through: {
model: 'A_B',
},
as: 'As',
foreignKey: 'b_id',
otherKey: 'a_id'
});
}
const A_B = sequelize.define('A_B', {
a_id: Sequelize.STRING,
b_id: Sequelize.STRING,
c_id: Sequelize.STRING
})
const C = sequelize.define('C', {
id: Sequelize.STRING
})
C.associate = function(models) {
C.hasMany(models.A_B, {
as: 'ABs',
foreignKey: 'c_id'
});
}
I try to create an associated table of tags with id of tag and id of related article, so first i do a findOrCreate tag, this function is operational and works perfectly, but when i do a then(function(result){}) and with the result i create my association with the id of the tag like result.id the id returned is null ! So in the case where i do a simple create it returns me an id, but when i do a findOrCreate the id is null !! What can i do to get the id of my created entry with findOrCreate function ? if there's another solution to create an entry that not already existing i'm also interested....here's my function in app.js
function(sales, callback) {
if(req.body.tags) {
tagsArray = req.body.tags.split(',');
var obj = tagsArray.reduce(function(acc, cur, i) {
acc[i] = cur;
return acc;
}, {});
callback(null, async.forEachOf(obj, (value,key,callback) => {
tagsFormattedArray.push({tags: value})
tagsController.create(req, res, value).then(function(result){
callback(null, tagSpottingController.create(req, res, result.id, idCreation))
})
}))
}
}
here's my tag controller :
module.exports = {
create(req, res, tag) {
return Tags
.findOrCreate({
where: {
name: tag
},
defaults: {
name: tag
}
})
}
};
here is my tag model :
module.exports = (sequelize, DataTypes) => {
const Tags = sequelize.define('Tags', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
name: {
type: DataTypes.STRING
},
createdAt: {
type: DataTypes.DATE,
field: 'createdAt'
},
updatedAt: {
type: DataTypes.DATE,
field: 'updatedAt'
}},{
timestamps: true
});
return Tags;
}
I read the doc and i tested to do this in my tag controller :
module.exports = {
findOrCreate(req, res, tag) {
return Tags
.findOrCreate({
where: {
name: tag
},
defaults: {
name: tag
}
}).spread((tags, created) => {
console.log(tags.get({
plain: true
}))
})
}
};
It console log all my created tags (the ones who are not in the db) that the behaviour that i wanted !...but when i try to do a return instead of a console log , to get my ids, it returns me only the false result (the one which already exists in the db)...there something that i don't understand
It seems that we cannot directly return the result of the spread so i had to push it inside a callback. Here my final code :
tagsController.findOrCreate(req, res, value).spread(function(tags, created){
if (created){
callback(null, tagSpottingController.create(req, res, tags.id, idCreation))
}
else {
callback(null, tagSpottingController.create(req, res, tags.id, idCreation))
}
})