How to solve "Not unique table/alias"? (node, sequelize) - node.js

I am implementing a comment service using 'express' and 'sequelize' modules. This comment service supports 'reply'. The model has 'user' and 'comment'.
Comment.hasMany(Comment, {foreignKey: {name: 'parent_comment', allowNull: true}, as: 'reply'});
Comment.belongsTo(Comment, {foreignKey: {name: 'parent_comment', allowNull: true}, as: 'parent'});
User.hasMany(Comment, {foreignKey: {allowNull: false}, onDelete: 'CASCADE'});
Comment.belongsTo(User, {foreignKey: {allowNull: false}, onDelete: 'CASCADE'});
I want to join the user by bringing in the "reply" part of the comment. like below...
[
{
somedata...,
writer: { // User model
userdata....
},
reply: [
{
somedata....
writer: { // User model
userdata....
}
},
....
]
},
....
]
However, as a result, an error occurs while outputting a message of 'Not unique table/alias'. Erase the marked 'this line' part and bring it normally, but it's not the desired result. code like this,
const c = await Comment.findAll({
include: [
{
model: User
},
{
model: Comment,
include: [{ model: User}] //// this line!
},
]
});
How can I get the results I want? Thank you.

Because Comment has 2 relationships with Comment (of course with aliases) you always need to indicate a desired alias in queries when you need to include Comment in Comment:
const c = await Comment.findAll({
include: [
{
model: User
},
{
model: Comment,
as: 'reply', // or as: 'parent' depending on your goal
include: [{ model: User}]
},
]
});

Related

Sequelize Aliases

I am working with sequelize and i have a model with two foreign keys
app.schemas.messengers.belongsTo(app.schemas.users, {
foreignKey: 'id_user_to',
as: 'to'
});
app.schemas.messengers.belongsTo(app.schemas.users, {
foreignKey: 'id_user_from',
as: 'from'
});
and the result of the query must return all messages of this specific user
this is the code of the query
return Users.findAll({
attributes: ['uuid', 'id', 'profile_pic', 'firstname', 'lastname', 'online'],
where: whereUser,
include: [{
model: Messengers,
as: 'from',
// as: 'to',
where: whereMessenger,
$or: [{
id_user_to: user.id,
},
{
id_user_from: user.id
}
],
order: [
['createdAt', 'ASC'],
],
}]
})
but only returns the message of users who write me not the messages to the user i wrote.
its there any way so I can put two aliases on the as attribute of sequelize, or is there other way to do so?
You have to include twice, e.g.
...
include: [
{
model: Messengers,
as: 'from'
/* other stuff */
},
{
model: Messengers,
as: 'to'
/* other stuff */
}
],
...
Also, you may have trouble with your alias names, as 'to' and 'from' are reserved words. I recommend msgTo and msgFrom instead...

left join on same table in sequelize

I want to write following query in sequelize but Not able to understand how to do.
SELECT * FROM RegisterUser AS RegisterUser
LEFT OUTER JOIN Notification as Noti ON PM_UserID = Noti.ReceiveID
LEFT OUTER JOIN RegisterUser AS RegisterUser1 ON
Noti.SenderId = RegisterUser1.PM_UserID
WHERE RegisterUser.PM_UserID = ReceiveID
I have written below query as a single left join and it works fine.
RegisterUser.findAll({
include: [
{
model: Notification,
as: 'NotificationrecipientId',
required: false,
},
],
raw: true });
And my assciotion is as follow:
db.RegisterUser.hasMany(db.Notifications, { as: 'NotificationrecipientId', foreignKey: 'ReceiveID' });
Sender ID as well in Register User table.
For that you have define one more association :
db.Notification.belongsTo(db.RegisterUser, { as: 'Sender', foreignKey: 'SenderId' });
and then use it like :
RegisterUser.findAll({
include: [{
model: Notification,
as: 'NotificationrecipientId',
required: false,
include: [{
model: RegisterUser,
as: 'Sender', // <---- HERE
required: false,
}, ]
}, ],
raw: true
});

Node.js sequelize model - can I define order of records on the model?

I am newish to node, and can't figure out how to only return 1 record of a hasMany relationship, based on an attribute.
There's a user, level, and levels_user table.
On user, I want to include 1 levels_user where level_id is highest.
Can I put a condition on this model file, something like:
order_by: ['level_id', 'DESC']
LevelsUsers Model
'use strict';
module.exports = (sequelize, DataTypes) => {
let LevelsUsers = sequelize.define('LevelsUsers', {
user_id: DataTypes.INTEGER,
level_id: DataTypes.INTEGER,
created_at: DataTypes.DATE,
updated_at: DataTypes.DATE,
},{
timestamps: false,
freezeTableName: true,
schema: "public",
tableName: "levels_users"
});
return LevelsUsers;
};
Users model association:
Users.hasMany(models.LevelsUsers, {
as: 'levels_users',
targetKey: 'id',
foreignKey: 'user_id',
});
This is my call:
users.getProfileByUserId = (req, res) => {
models.Users.findOne({
where: {id: req.params.userid},
include: [
{
model: models.LevelsUsers,
as: 'levels_users',
limit: 1,
}
]
order: []
}).then(user ....
I tried adding:
`order: [
[ models.LevelsUsers , 'level_id', 'DESC']
]`
Did not work and I think it's evaluated after limit: 1 anyways.
Can I put order_by on the model, to return highest to lowest by level_id each time? If not, what's a better way to accomplish returning only the highest levels_users record where level_id is highest?
The hasMany property is more suited when you want to include all the levels in the user object. In your case, I would advise to just pull the user without it's levels, and then do a second request to pull the higher level linked to that user by querying directly the LevelsUsers model :
models.LevelsUsers.findAll({
where: {
user_id: user.id,
},
order: ['level_id', 'DESC'],
limit: 1,
});
Well i reading over the documentation of sequelize for working with ordering and limit inside the includes tag.
Update query
users.getProfileByUserId = (req, res) => {
models.Users.findOne({
where: {id: req.params.userid},
include: [
{
model: models.LevelsUsers,
as: 'levels_users',
order: [
[ { model: models.LevelsUsers }, 'level_id', 'DESC']
],
limit: 1,
}
]
}).then(user ....
For references go over the following links - https://github.com/sequelize/sequelize/issues/4553#issuecomment-341261957

unknown column in field list sequelize

I'm trying to perform the following query using Sequelize:
db.Post.findAll({
include: [
{
model: db.User,
as: 'Boosters',
where: {id: {[Op.in]: a_set_of_ids }}
},
{
model: db.Assessment,
as: 'PostAssessments',
where: {UserId: {[Op.in]: another_set_of_ids}}
}
],
attributes: [[db.sequelize.fn('AVG', db.sequelize.col('Assessments.rating')), 'average']],
where: {
average: 1
},
group: ['id'],
limit: 20
})
But I run to this error: "ER_BAD_FIELD_ERROR". Unknown column 'Assessments.rating' in 'field list', although I do have table "Assessments" in the database and "rating" is a column in that table.
My Post model looks like this:
const Post = sequelize.define('Post', {
title: DataTypes.TEXT('long'),
description: DataTypes.TEXT('long'),
body: DataTypes.TEXT('long')
}, {
timestamps: false
});
Post.associate = function (models) {
models.Post.belongsToMany(models.User, {as: 'Boosters', through: 'UserPostBoosts' });
models.Post.hasMany(models.Assessment, {as: 'PostAssessments'});
};
What am I doing wrong?
It seems like this problem surfaces when we have a limit in a find query where associated models are included (the above error doesn't show up when we drop the limit from the query). To solve that, we can pass an option subQuery: false to the find. (https://github.com/sequelize/sequelize/issues/4146)
This is the correct query in case anyone comes across the same problem:
db.Post.findAll({
subQuery: false,
include: [
{
model: db.User,
as: 'Boosters',
where: {id: {[Op.in]: a_set_of_ids }}
}
,{
model: db.Assessment,
as: 'PostAssessments',
where: {UserId: {[Op.in]: another_set_of_ids}}
}
],
having: db.sequelize.where(db.sequelize.fn('AVG', db.sequelize.col('PostAssessments.rating')), {
[Op.eq]: 1,
}),
limit: 20,
offset: 2,
group: ['Post.id', 'Boosters.id', 'PostAssessments.id']
})
Error is with this one :
models.sequelize.col('Assessments.rating'))
Change it to
models.sequelize.col('PostAssessments.rating')) // or post_assessments.rating
Reason : You are using the alias for include as: 'PostAssessments',.

Sequelize query on join table

I am trying to querying a join table using sequelize:
Here is the model:
db.client.belongsToMany(db.user, {
through: db.clientUser,
onDelete: 'cascade',
});
db.user.belongsToMany(db.client, {
through: db.clientUser,
});
and this is what I am trying to do:
db.user.findAll({
where: {
group_id: 1,
},
include: [{
model: db.clientUser,
where: {
is_manager: 1,
}
}],
raw: true,
})
However I get the following error: client_user is not associated to user!
Any idea what could be the cause of this issue?
You declared a relationship between client from user through clientUser. Although pedantic, its complaint is technically correct: there is no explicitly declared relationship declared between client and clientUser. Nor should there be: your belongsToMany relationship should take care of that. Your query can be adjusted to work with this relationship.
Note: I don't know what tables group_id and is_manager are found in. They may need to be shuffled around.
db.user.findAll({
where: {
group_id: 1,
},
include: [{
model: db.client,
through: {
where: {
is_manager: 1, // Assuming clientUser.is_manager?
},
}],
raw: true,
})

Resources