complicated query using sequelize - node.js

i have 3 tables .. profile, player, garage
profile has winCount , loseCount
player has username
garage has carNumber
they are all connected with each other using the id from player table (playerId in table garage and profile)
i want to get the
top 20 winCount , username , carnumber
i am trying this code
let racers = await Profile.findAll({
where: {
carRaceWinCount: {
[Op.gt]: 0
}
},
limit: 20,
order: [
['carRaceWinCount', 'DESC']
]
})
.then((races: any) => {
Garage.findAll({
where: {
playerId: races.id
},
attributes : ['carNum']
})
Player.findAll({
where :{
id : races.id
},
attributes : ['username']
})
})
and it is not working
what is the best way to get this query

If you have these associations:
Player.hasMany(Profile, { foreignKey: 'playerId' })
Player.hasMany(Garage, { foreignKey: 'playerId' })
Profile.belongsTo(Player, { foreignKey: 'playerId' })
then the query might look like this
await Profile.findAll({
where: {
winCount: {
[Op.gt]: 0
}
},
limit: 20,
include: [{
model: Player,
include: [{
model: Garage,
// this is important option to query all garames as separate queries, Otherwise you will get wrong count of profiles.
separate: true
}]
}]
order: [
['winCount', 'DESC']
]
})

Related

Counting number of associated rows in sequelize

I am trying to find the count of students inside the classStudents association. Here teacher_details table is connected to class_details tables using 'section'
association and class_details tables is connected to student_details table using 'classStudents' association. I have tried the below method but got error ==>
Unknown column 'section->classStudents.studentId' in 'field list'
please let me know the correct procedure to count the associated students count
const getAssignedDetails = async (req, res) => {
try {
const assignedDetails = await Entity.teacherAssignedDetail.findAll({
where: { status: 1, teacherId: req.teacherId },
attributes: [
'role',
[
Sequelize.fn(
'COUNT',
Sequelize.col('section.classStudents.studentId')
),
'studentCount',
],
],
include: [
{
association: 'section',
attributes: ['sectionId', 'className', 'classEmoji'],
include: [
{
association: 'classStudents',
where: { status: 1 },
required: false,
},
],
where: { status: 1 },
},
{
association: 'subjectDetails',
attributes: [['id', 'masterSubjectId'], 'subjectName'],
},
],
});
res.json({
responseCode: 0,
responseMessage: 'Success',
responseData: assignedDetails,
});
} catch (err) {
res.status(500).send(errorHandling(err.message));
}
};

Sequelize - Select on associated table

My problem:
I am creating an route which will return some informations about a group, it has an id, an user assigned and also has some documents. I just want to show how much documents exists, in SQL would be SELECT COUNT, but how can i do this in this in sequelize?
My code:
async list(req, res){
const docGroups = await DocGroup.findAll({
raw: true,
include: [{
model: User,
as: 'userAssigned'
},
{
model: Document,
as: 'Document'
}
]
}).then(groups => {
const result = groups.map(group => {
return Object.assign(
{},
{
id: group.id,
name: group.name,
userAssinged: group['userAssigned.firstName'],
docAmount: // I want to put documents' count here
}
)
})
console.log(groups)
})
}
What is printed in console.log(groups):
[
{
id: 1,
name: 'pleaseworks',
createdAt: 2020-06-10T02:38:11.531Z,
updatedAt: 2020-06-10T02:38:11.531Z,
'userAssigned.id': 1,
'userAssigned.firstName': 'Please',
'userAssigned.lastName': 'Works',
'userAssigned.email': 'pleaseworks#gmail.com',
'userAssigned.password': '$2a$08$3BA4I4dsaQ3lsHy342344b5P41v5eHWjwqv6dve28nSdqbGvhsdS',
'userAssigned.createdAt': 2020-06-10T02:37:29.062Z,
'userAssigned.updatedAt': 2020-06-10T02:37:29.062Z,
'userAssigned.groupId': null,
'Document.id': 2,
'Document.description': 'deowkdopewkdwe',
'Document.content': 'odepodkewokodwe',
'Document.groupId': 1,
'Document.createdAt': 2020-06-10T02:43:46.005Z,
'Document.updatedAt': 2020-06-10T02:43:46.005Z
}
]
If DocGroup has many Document try something like this:
{
model: Document,
attributes: [[sequelize.fn('COUNT', sequelize.col('id')), 'docAmount']]
as: 'Document'
}

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 and querying on complex relations

I'm trying to understand how best to perform a query over multiple entities using Sequelize and Node.js.
I have defined a model "User" which has a belongsToMany relation with a model "Location". I then have a model "Asset" which also has a belongsToMany relation with "Location". When I have an instance of a User I would like to fetch all Assets that are associated with Locations that the User is associated with.
I tried the following which doesn't seem to work...
user.getLocations().then(function(userLocations) { return Asset.findAll({ where: { "Locations" : { $any : userLocations } }) })
Could anyone offer any suggestions?
Try this query:
User.findById(user_id, {
include: [{
model: Location,
required: true
}]
}).then(user => Asset.findAll({
where: {
user_id: user.id,
location_id: {
$in: user.locations.map(location => location.id)
}
}
})).then(assets => {
// The rest of your logic here...
});
This was the final result...
User.findById(user_id, {
include: [{
model: Location,
as: 'Locations', // Was needed since the original relation was defined with 'as'
required: true
}]
}).then(user => Asset.findAll({
include: [{
model: Location,
as: 'Locations',
where: {
id: {
$in: user.Locations.map(location => location.id)
}
}
}]
})).then(assets => {
// The rest of your logic here...
});

Resources