how can i use limit in include model using sequelize - node.js

i want to get user's images at limit 2 from Follow model.
Models
const Follow = connector.define('Follow', {
no: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
follower_id: {
type: Sequelize.INTEGER,
allowNull: true
},
target_id: {
type: Sequelize.INTEGER,
allowNull: true
},
isDelete: {
type: Sequelize.BOOLEAN,
allowNull: false
},
create_dt,
delete_dt
}
const User = connector.define('User', {
no: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
username: {
type: Sequelize.STRING,
allowNull: false
},
email: {
type: Sequelize.STRING,
allowNull: false
},
password: {
type: Sequelize.STRING,
allowNull: false
},
profile_img: {
type: Sequelize.STRING,
allowNull: true
},
bio: {
type: Sequelize.STRING,
allowNull: true
},
phone: {
type: Sequelize.STRING,
allowNull: true
},
gender: {
type: Sequelize.STRING,
allowNull: true
},
website: {
type: Sequelize.STRING,
allowNull: true
},
isDelete: {
type: Sequelize.BOOLEAN,
allowNull: false
},
create_dt,
update_dt,
delete_dt
}
const Image = connector.define('Image', {
no: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
file: {
type: Sequelize.STRING,
allowNull: false
},
location: {
type: Sequelize.STRING,
allowNull: true
},
caption: {
type: Sequelize.STRING,
allowNull: true
},
tags: {
type: Sequelize.STRING,
allowNull: true
},
isDelete: {
type: Sequelize.BOOLEAN,
allowNull: false
},
create_dt,
update_dt,
delete_dt,
user_id: {
type: Sequelize.INTEGER,
allowNull: true
}
}
and, join
User.hasMany(Image, {foreignKey: 'user_id'})
Image.belongsTo(User, {foreignKey: 'user_id'})
User.hasMany(Follow, {foreignKey: 'follower_id'})
Follow.belongsTo(User, {foreignKey: 'follower_id'})
User.hasMany(Follow, {foreignKey: 'target_id'})
Follow.belongsTo(User, {foreignKey: 'target_id'})
so, i tried get user's images from follow by use include.
const followerImages = await Follow.findAll({
attributes: ['target_id'],
where:{
follower_id: loginUser_id
},
include:[
{
model: User,
required: true,
attributes: ['username', 'email', 'profile_img'],
include:[
{
model: Image,
required: true
}
]
}
]
})
but i want to get images at limit 2.
so i tried that
const followerImages = await Follow.findAll({
attributes: ['target_id'],
where:{
follower_id: loginUser_id
},
include:[
{
model: User,
required: true,
attributes: ['username', 'email', 'profile_img'],
include:[
{
model: Image,
required: true,
limit: 2
}
]
}
]
})
but it makes bugs i cant understand.
images field is a array contain empty object at 4.
all same..
what is the problem?
how can i solve this problem??

You can try :
include:[
{
model: Image,
attributes : ['id','user_id','image'] , // <---- don't forget to add foreign key ( user_id )
separate : true, // <--- Run separate query
limit: 2
}
]
Limit causes the issues some time on nested level , so it always safe to run that query separately.

Related

Query in join-table for N:M associations in Node JS and Sequelize

I have a classical many-to-many relationship for users which own assets: assets can be transfered to other users during their life so a window time is recorded in the AssetUser "through table",
adding STARTDATE and ENDDATE attributes.
User Table
const User = sequelize.define('User', {
ID: {
type: DataTypes.INTEGER.UNSIGNED,
allowNull: false,
primaryKey: true
},
FIRSTNAME: {
type: DataTypes.STRING,
allowNull: false
},
LASTNAME: {
type: DataTypes.STRING,
allowNull: false
}},{ timestamps: false }});
Asset Table
const Asset = sequelize.define('Asset', {
ID: {
type: DataTypes.INTEGER.UNSIGNED,
allowNull: false,
primaryKey: true
},
DESCRIPTION: {
type: DataTypes.STRING,
allowNull: false
}},{ timestamps: false }});
AssetUser Join Table
const AssetUser = sequelize.define('AssetUser', {
id: {
type: DataTypes.INTEGER.UNSIGNED,
primaryKey: true,
autoIncrement: true,
allowNull: false
},
UserID: {
type: DataTypes.INTEGER.UNSIGNED,
references: {
model: User,
key: 'ID'
}
},
AssetID: {
type: DataTypes.INTEGER.UNSIGNED,
references: {
model: Asset,
key: 'ID'
}
},
STARTDATE: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW
},
ENDDATE: {
type: DataTypes.DATE,
allowNull: true,
defaultValue: null
}},{ timestamps: false });
The models are created here:
User.belongsToMany(Asset, { through: { model: AssetUser, unique: false }, uniqueKey: 'id' });
Asset.belongsToMany(User, { through: { model: AssetUser, unique: false }, uniqueKey: 'id' });
My problem is that I want to query and find all the results where one asset, owned by one user, during a restricted period. I am not able to query the join-table but only User and Assets tables.
How can I add a "where" condition for the AssetUser table inside my query? How should I insert a STARTDATE and/or ENDDATE condition below?
Asset.findAll({
where: {
DESCRIPTION: 'Personal computer'
},
include: {
model: User,
where: {
FIRSTNAME: 'Marcello'
}
}});
Thanks for your help.
I found the solution
Asset.findAll({ where: { DESCRIPTION: 'Personal computer' }, include: { model: User, through: { where: { FIRSTNAME: 'Marcello' } } }});

Sequelize hasOne join: Include unexpected. Element has to be either a Model, an Association or an object

I want to establish a relationship between two tables using a foreign key to read me the description (funzione string(40)). My models and code:
first model:
id: {
autoIncrement: true,
type: Sequelize.INTEGER,
allowNull: false,
primaryKey: true
},
id_user: {
type: Sequelize.INTEGER,
allowNull: false
},
id_role: {
type: Sequelize.INTEGER,
allowNull: false
},
id_funzione: {
type: Sequelize.INTEGER,
allowNull: false
}
}, {
sequelize,
tableName: 'abilitazioni',
schema: 'public',
timestamps: false,
indexes: [
{
name: "pk_abilitazioni",
unique: true,
fields: [
{ name: "id"},
]
},
]
Second model:
id: {
autoIncrement: true,
type: Sequelize.INTEGER,
allowNull: false,
primaryKey: true
},
funzione: {
type: Sequelize.STRING(40),
allowNull: false
}
}, {
sequelize,
tableName: 'funzioni',
schema: 'public',
timestamps: false,
indexes: [
{
name: "pk_funzioni",
unique: true,
fields: [
{ name: "id_funzione" },
]
},
]
The relation
db.Abilitazioni.hasOne(db.Funzioni, {
foreignKey: 'id_funzione'
});
db.Funzioni.belongsTo(db.Abilitazioni);
find on db
Abilitazioni.findAll({
where: { id_role: id
},
include: [{
Funzioni,
}]
})
I tried to create a one to one relationship to read a description
field with the foreign key.
This query :
SELECT funzioni.id , funzioni.funzione , funzioni.access_level
from public.abilitazioni, public.funzioni
where abilitazioni.id_user = 1 and id_role= 1 and
abilitazioni.id_funzione = funzioni.id ;

Sequelize hasMany assocaition

I am considering these 2 tables "exam_response" and "answer" for hasMany association.
Where both the tables contains "question_id". Using question_id I need the answers.
exam_response table
module.exports = (sequelize, DataTypes) => {
const exam_response = sequelize.define('exam_response', {
id: {
allowNull: false,
primaryKey: true,
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4
},
session_id: {
type: DataTypes.UUID,
allowNull: false
},
exam_id: {
type: DataTypes.UUID,
allowNull: false
},
user_id: {
type: DataTypes.UUID,
allowNull: false
},
question_id: {
type: DataTypes.UUID,
allowNull: false
},
answer_ids: {
type: DataTypes.ARRAY(DataTypes.UUID),
allowNull: false
},
is_correct: {
type: DataTypes.BOOLEAN,
allowNull: false
},
is_bookmarked: {
type: DataTypes.BOOLEAN,
allowNull: false
},
is_attempted: {
type: DataTypes.BOOLEAN,
allowNull: false
},
createdAt: {
type: DataTypes.DATE,
field: 'created_at'
},
updatedAt: {
type: DataTypes.DATE,
field: 'updated_at'
}
}, {});
exam_response.associate = function (models) {
// associations can be defined here
exam_response.hasMany(models.answer, {
foreignKey: 'question_id', sourceKey: 'question_id',as:'exam_answers'
});
};
answer table
'use strict';
module.exports = (sequelize, DataTypes) => {
const answer = sequelize.define('answer', {
//{
// "id":"",
// "question_id":"123",
// "position":0,
// "answer":"This is answer 1."
// }
id: {
allowNull: false,
primaryKey: true,
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4
},
question_id: {
allowNull: false,
type: DataTypes.UUID
},
position: {
allowNull: false,
type: DataTypes.INTEGER
},
answer: {
allowNull: false,
type: DataTypes.TEXT
},
publish_status: {
allowNull: false,
type: DataTypes.ENUM('published', 'unpublished', 'deleted')
},
language: {
type: DataTypes.ENUM('en', 'kn', 'hi')
},
createdAt: {
type: DataTypes.DATE,
field: 'created_at'
},
updatedAt: {
type: DataTypes.DATE,
field: 'updated_at'
}
}, {});
answer.associate = models => {
answer.belongsTo(models.question,{foreignKey:'question_id',as:'answers'});
answer.belongsTo(models.exam_response,{foreignKey:'question_id', targetKey: 'question_id',as:'exam_answers'});
};
return answer;
};
Query::
ExamResponse.findAll({
where: {
exam_id
},
include: [
{
model: Answer,as:'exam_answers'
}
],
}).then(resp => {
response.successGet(res, resp, 'Exam Response');
}).catch(next)
I am getting the output but associated part("exam_answers") is empty.
If I use raw query, i am able to get the output. But the Query is only fetching me the exam_response not the answer even though the value exists.

sequelize - inner join gives an error after added a foreign key

i have these 2 models:
module.exports = function(sequelize, DataTypes) {
return sequelize.define('services_prices', {
id: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true
},
service_id: {
type: DataTypes.INTEGER(11),
allowNull: true,
references: {
model: 'services',
key: 'id'
}
},
created_at: {
type: DataTypes.DATE,
allowNull: false
},
limit: {
type: DataTypes.INTEGER(11),
allowNull: true
},
price: {
type: DataTypes.INTEGER(11),
allowNull: true
}
});
};
which is parent of this model: (services_user_prices can override services_prices )
module.exports = function(sequelize, DataTypes) {
return sequelize.define('services_user_prices', {
id: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
autoIncrement: true
},
user_id: {
type: DataTypes.INTEGER(11),
allowNull: true
},
created_at: {
type: DataTypes.DATE,
allowNull: false
},
currency: {
type: DataTypes.STRING(255),
allowNull: true
},
is_active: {
type: DataTypes.INTEGER(1),
allowNull: true,
defaultValue: '0'
},
is_trial: {
type: DataTypes.INTEGER(1),
allowNull: true,
defaultValue: '0'
},
start_date: {
type: DataTypes.DATE,
allowNull: false
},
end_date: {
type: DataTypes.DATE,
allowNull: true
},
price: {
type: DataTypes.INTEGER(11),
allowNull: true
},
bundle_price_id: {
type: DataTypes.INTEGER(11),
allowNull: true,
references: {
model: 'services_prices',
key: 'id'
}
}
});
};
when trying to join them i get an error:
EagerLoadingError: services_prices is not associated to services_user_prices!
const result= await db.services_user_prices.findOne({
where: { is_active: 1, user_id: 123 }, include:[{db.services_prices}]
});
in the db services_user_prices has foreign key to services_prices table
what am i doing wrong?
Well if you are using sequelize then you need to update your model because
by default, sequelize will be looking for foreign key starts with model name like
you have defined bundle_price_id as a foreign key for services_prices.
You need to change your column name to services_price_id then it will get fixed.
or if you want to use bundle_price_id you need to define it in your model relation as.
Model.belongsTo(models.ModelName, { foreignKey: 'your_key'} )
Please feel free if you need to ask anything else.
As complement of the above answer you need to add an identifier with as: on the association like this:
Model.belongsTo(models.ModelName, { foreignKey: 'your_key', as:'your_identifier' } )
Then when you do the include on the method you also call the identifier:
await db.services_user_prices.findOne({
where: { is_active: 1, user_id: 123 },
include:[{
model: db.services_prices
as: 'your_identifier'
}]
});
If you don't define the foreignKey field, the as field will set the column name.

How to create an associated object in Sequelize / Node.js ?

There is 2 models:
sequelize.define('Hotel', {
id: {
autoIncrement: true,
type: DataTypes.INTEGER,
primaryKey: true
},
latitude: {
type: DataTypes.DOUBLE,
allowNull: false
},
longitude: {
type: DataTypes.DOUBLE,
allowNull: false
},
title: {
type: DataTypes.STRING,
allowNull: false
},
description: {
type: DataTypes.TEXT,
allowNull: false
},
rating: {
type: DataTypes.DOUBLE,
defaultValue: 0
},
image: {
type: DataTypes.STRING
}
}, {
classMethods: {
associate: function(db) {
Hotel.hasMany(db.Comment, {
foreignKey: 'commentable_id',
scope: {
commentable: 'hotel'
}
});
}
}
});
And
sequelize.define('Comment', {
id: {
type: DataTypes.INTEGER,
primaryKey: true
},
content: {
type: DataTypes.TEXT,
allowNull: false
},
commentable: DataTypes.STRING,
commentable_id: DataTypes.INTEGER
});
How can I create associated Comment for existing Hotel instance? For example, I've tried:
hotel.addComment(request.models.Comment.create({content: 'content'}))
But it doesn't work. Please, tell me, how I can fix it? Thanks in advance!
request.models.Comment.create() is async, in other words it returns a promise that must be fullfilled before you can use the resolved value to 'feed' the addComment method.
So you should do something like
request.models.Comment.create({content: 'content'}).
then(function(comment){
return hotel.addComment(comment);
});

Resources