How to get Associated model row count in Sequelize? - javascript

Hi I have a following code. From this I need a total rows count from the Comment Model. Can you please help? Thanks in Advance!
Post.hasMany(models.Comment, {
as: 'postComment',
foreignKey: 'postId',
});
Comment.belongsTo(models.Post, {
foreignKey: 'postId',
as: 'post',
});
return Post.findAndCountAll({
attributes: [['postId', 'id'], 'target_population', 'title', ['type', 'category'], 'stage', ['text_content', 'comment'], ['time_posted', 'engagement_timeframe'], ['closing_date', 'engagement_completion'], ['engagement_end', 'engagement_close'], ['non_constituent_view', 'non_constituents'], ['discussion_board_enabled', 'discussion_board'], 'attached_documents', 'description'],
where: where,
offset: offset,
limit: limit,
distinct: true,
include: [
{
model: Survey,
as: 'survey',
attributes: ['isOpen'],
where: {isOpen: "TRUE"},
required: false,
include: [
{
model: Question,
as: 'question',
include: [
{
model: ProposedAnswer,
as: 'choice',
attributes: [['proposedAnswerId', 'id'], ['answer', 'value']],
required: false,
}
],
attributes: [['questionId', 'id'], ['question', 'title'], ['questionType', 'type']]
}
]
},
{
model: User,
as: 'user',
attributes: ['first_name'],
where: {userId: {[Op.not]: null}},
},
{
model: Topic,
as: 'topic',
attributes: [['topicId', 'id'], ['name', 'value']],
through: {attributes: []},
},
{
model: Comment,
as: 'postComment',
},
],
order: [
['postId', 'DESC'],
]
})

Related

Problem ordering sequelize query by date, in ascending order

I need to order a sequelize query by date ascending. What I'm trying to sort out is the result of the model: ExamScore (as student_score).
Note that in the ordering I am setting the column "updated_at" and the way of ordering. However, it is not working, it simply does not order.
const students = await Students.findAll({
attributes: ['id', 'name', 'cpf'],
include: [
{
model: Status,
attributes: ['status', 'updated_at'],
as: 'student_status',
where: [{ course_id }],
required: false,
},
{
model: ExamScore,
attributes: ['score', 'updated_at'],
as: 'student_score',
where: [{ module_id }],
required: false,
order: [['updated_at', 'ASC']],
},
],
});
Below is an example of the return from this query:
{
"id": 30014,
"name": "Jon Doe",
"cpf": "xxxxxxxx",
"student_status": [
{
"status": "APROVADO",
"updated_at": "2021-05-27T03:06:14.502Z"
}
],
"student_score": [
{
"score": "9.00",
"updated_at": "2021-05-27T03:06:13.998Z"
},
{
"score": "2.00",
"updated_at": "2021-05-27T02:59:22.571Z"
}
]
},
I can't understand what I'm doing wrong.
Try adding order to your top query, not inside includes.
Example:
const students = await Students.findAll({
attributes: ['id', 'name', 'cpf'],
include: [
{
model: Status,
attributes: ['status', 'updated_at'],
as: 'student_status',
where: [{ course_id }],
required: false,
},
{
model: ExamScore,
attributes: ['score', 'updated_at'],
as: 'student_score',
where: [{ module_id }],
required: false,
},
],
// add the order, model ExamScore with alias student_score
order: [[{ model: ExamScore, as: 'student_score' }, 'updated_at', 'ASC']],
});

Sequelize - Include based on specific attribute

I have a model defined as follows:
sequelize.define('game', {
id: {
type: type.INTEGER,
primaryKey: true,
autoIncrement: true,
},
leaderId: {
type: type.INTEGER,
allowNull: false,
references: {
model: 'users',
key: 'id',
},
},
playerId: {
type: type.INTEGER,
allowNull: false,
references: {
model: 'users',
key: 'id',
},
},
status: {
type: type.STRING,
defaultValue: 'running',
},
notes: {
type: type.TEXT,
},
});
I'm trying to use Sequelize to load all game object and include the User with the id equal to the playerId field.
The problem is I have two attributes (leaderId, playerId) which reference the User model so using include as follows does not work:
Game.findAll({
where: conditions,
include: [{ model: User }],
})
Is there a way to specify which attribute the include command should use?
const game = sequelize.define('game', {
id: {
type: type.INTEGER,
primaryKey: true,
autoIncrement: true,
},
leaderId: {
type: type.INTEGER,
allowNull: false,
references: {
model: 'users',
key: 'id',
},
},
playerId: {
type: type.INTEGER,
allowNull: false,
references: {
model: 'users',
key: 'id',
},
as:'player'
},
status: {
type: type.STRING,
defaultValue: 'running',
},
notes: {
type: type.TEXT,
},
});
game.associate = function (models) {
game.belongsTo(models.user, {
foreignKey: "playerId",
as: "player",
});
game.belongsTo(models.user, {
foreignKey: "leaderId",
as: "leader",
});
};
Game.findAll({
where: conditions,
include: ['player'],
})
Or
Game.findAll({
where: conditions,
include: [{model: User, as: 'player' }],
})
Or
Game.findAll({
where: conditions,
include: [{model: User, as: 'player', foreignKey: 'playerId' }],
})
https://github.com/nkhs/node-sequelize

Get data that contains all the ids of the array

I'm trying to make a filter songs, i have an array of genres ids that i retrieve from the client, i do this for get all the audios from one id:
Audio.findAll({
include: [{
model: db.Genres,
as: "genres",
where: {
id: {
[Op.and]: [1]
}
},
}]
})
But i need to get all audios that contains all the ids from array of genres/moods, also want filter audios by genres ids and moods ids, but i don't know how to make it, any idea? (One song can have many genres/moods)
Song Model
const Audio = sequelize.define('Audio', {
id: {
autoIncrement: true,
type: DataTypes.INTEGER(30),
allowNull: false,
primaryKey: true
},
name: {
type: DataTypes.STRING(255),
allowNull: false
},
})
Audio.associate = function(models) {
Audio.belongsToMany(models.Genres, {through: 'AudioGenres', foreignKey: 'id_audio', as: 'genres'})
Audio.belongsToMany(models.Moods, {through: 'AudioMoods', foreignKey: 'id_audio', as: 'moods'})
}
AudioGenreModel
const AudioGenres = sequelize.define('AudioGenres', {
id_audio: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
references: {
model: 'Audio',
key: 'id'
}
},
id_genre: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
references: {
model: 'Genres',
key: 'id'
}
})
AudioGenres.associate = function(models) {
AudioGenres.belongsTo(models.Audio, {foreignKey: 'id_audio'})
AudioGenres.belongsTo(models.Genres, {foreignKey: 'id_genre'})
};
AudioMoodModel
const AudioMoods = sequelize.define('AudioMoods', {
id_audio: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
references: {
model: 'Audio',
key: 'id'
}
},
id_mood: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
references: {
model: 'Mods',
key: 'id'
}
})
AudioMoods.associate = function(models) {
AudioMoods.belongsTo(models.Audio, {foreignKey: 'id_audio'})
AudioMoods.belongsTo(models.Mods, {foreignKey: 'id_mood'})
};
Moods and Genres Model
const Moods = sequelize.define('Moods', {
name: {
type: DataTypes.STRING(255),
allowNull: false
},
})
Moods.associate = function(models) {
Moods.belongsToMany(models.Audio, {through: 'AudioMoods', foreignKey: 'id_mood', as: 'audios'})
}
const Genres = sequelize.define('Genres', {
name: {
type: DataTypes.STRING(255),
allowNull: false
},
})
Genres.associate = function(models) {
Genres.belongsToMany(models.Audio, {through: 'AudioGenres', foreignKey: 'id_genre', as: 'audios'})
}
I suppose you should add all conditions in AND operator in both include options like this:
Audio.findAll({
include: [{
model: db.Genres,
as: "genres",
where: {
[Op.and]: [{ id: 1}, { id: 3},{ id: 2}]
},
}, {
model: db.Moods,
as: "moods",
where: {
[Op.and]: [{ id: 4}, { id: 5},{ id: 6}]
},
}]
})

Sequelize and nested results?

Sequelize allows for data relationships, but I can't seem to see if there is a way to have it return a query result composed of the relation? I could do this as two queries, but I am curious as to whether Sequelize provides for this? For example Playlist and PlaylistEntry:
Playlist: sequelize.define('playlist', {
name: Sequelize.STRING,
description: Sequelize.STRING
}),
PlaylistEntry: sequelize.define('playlist_entry', {
playlist: Sequelize.INTEGER
//track: Sequelize.INTEGER
})
PlaylistEntry.belongsTo(
Playlist,
{ as: 'Playlist', foreignKey: { name: 'fk_playlist' }});
What I would be hoping for (pseudocode):
Query:
Playlist.find(where: {id: playlistId}, nestedResult: true);
Result:
[{
id: 123,
name: 'abc'
playlistEntries: [{
id: 321,
track: 431
}]
}]
Playlist.find({
where: {},
include: [
{model: PlaylistEntry} //this should be PlaylistEntry model
]
})
http://docs.sequelizejs.com/en/latest/docs/models-usage/#eager-loading

How to reference two tables using hasOne with sequelize.js

Considering these 3 models generated by sequelize-auto:
sequelize.define('users', {
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
first: {
type: DataTypes.STRING,
allowNull: true
},
last: {
type: DataTypes.STRING,
allowNull: true
}
}, {
tableName: 'users',
underscored: true,
timestamps: false
});
sequelize.define('groups', {
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
parent_id: {
type: DataTypes.INTEGER,
allowNull: true,
references: {
model: 'groups',
key: 'id'
}
}
}, {
tableName: 'groups',
underscored: true,
timestamps: false
});
sequelize.define('user_groups', {
group_id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
references: {
model: 'groups',
key: 'id'
}
},
user_id: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: 'users',
key: 'id'
}
}
}, {
tableName: 'user_groups',
underscored: true,
timestamps: false
});
I was expecting hasOne statements to be generated but I had to specify them like so:
user_groups.hasOne(orm.models.users, { foreignKey: "id" });
user_groups.hasOne(orm.models.groups, { foreignKey: "id" });
Also consider the following data in tables:
users (id, first, last):
1, John, Doe
group (id, parent_id):
1, NULL
2, NULL
3, NULL
4, NULL
user_groups (group_id, user_id):
1, 1
4, 1
Doing this query:
sequelize.findAll("user_groups", {
attributes: ["*"],
raw: true,
include: [{
model: models.users,
}]
});
I get the following results:
[ { group_id: 4,
user_id: 1,
'user.id': null,
'user.first': null,
'user.last': null },
{ group_id: 1,
user_id: 1,
'user.id': 1,
'user.first': 'John',
'user.last': 'Doe' } ]
This clearly shows that sequelize is using group_id for the user_id relation.
How can I specify a relation that links the user_groups relations to their respective tables in order to be able to associate a user to many groups?
I am also very curious as how the "references" key in the models definition is supposed to work as the documentation is inexistant on that.
I was able to get the referenced data using these associations:
groups.hasMany(orm.models.user_groups);
user_groups.belongsTo(orm.models.groups, {foreignKey: "group_id", as: "group"});
users.hasMany(orm.models.user_groups);
user_groups.belongsTo(orm.models.users, {foreignKey: "user_id", as: "user"});
And the following query:
sequelize.findAll("user_groups", {
attributes: ["*"],
raw: true,
include: [
{ model: users, foreignKey: "user_id", as: "user", attributes: ["first", "last"] }
]
});
With the expected results:
[ { group_id: 4,
user_id: 1,
'user.first': 'John',
'user.last': 'Doe' },
{ group_id: 1,
user_id: 1,
'user.first': 'John',
'user.last': 'Doe' } ]

Categories