FindAll WHERE using include with alias field in sequelize - mysql

How to perform FindAll with WHERE using alias include association
Now I have this code :
Photobook.findAndCountAll({
include: [
{
attributes: ['full_name'],
as: 'layouter_name',
model: UserModel,
},
{
attributes: ['full_name'],
as: 'current_pic',
model: UserModel,
}
],
where:{
{
'$current_pic.full_name$' : {
$like: '%name%'
}
}
}
});
It doesn't work since the Photobook model don't have current_pic.full_name field. I just want to search the current_pic association instead of layouter_name association.
How to perform something like that ?

Try this:
Photobook.findAndCountAll({
include: [
{
attributes: ['full_name'],
as: 'layouter_name',
model: UserModel,
},
{
attributes: ['full_name'],
as: 'current_pic',
model: UserModel,
where: {
full_name: {
$like: '%name%'
}
},
required: true
}
]
});
You can give where condition in the include array itself. required: true ensures that the JOIN is treated as INNER JOIN

Related

How to do where condition on include relation in Loopback

I want to get the result with include relation with where condition on include model.
return this.htcApi.find({
include: [
{
relation: 'nmos',
scope: {
include: 'countries',
},
},
],
where: { name:'Welcome', "nmos.name":'agile'}
});
This where is condition work for name of htc model not for noms module.
I want query like
Select htc.*, nmos.* FROM htc LEFT JOIN nmos ON nmos.id = htc.n_id where htc.name = 'abc' and nmos.name = 'abc';
How can add where condition on the "relation" table?
Simply you need to add where clause in 'scope' object which lies inside the 'include' object. So the code would be like :
return this.htcApi.find({
include: [
{
relation: 'nmos',
scope: {
include: 'countries',
where:{name:'agile'}
},
},
],
where: { name:'Welcome'}
});
In your query, you just need to add the property where within the scope property, like this:
return this.htcApi.find({
include: [
{
relation: 'nmos',
scope: {
include: 'countries',
where: {
and [
{ id: htc.n_id },
{ name: 'abc' },
],
},
},
},
],
where: { name: 'abc' }
});
This should return the htcApi objects named 'abc' with the related nmos objects that have the name 'abc' and the id 'n_id'.

Sequelize select only chosen attributes

I am using MySQL database, when I am doing:
models.modelA.findAll({
attributes: [
['modelA.id','id']
],
raw: true,
include:
[
{
model: models.modelB,
required: true
}
]
}).then(function (tenants) {
});
Nevertheless that I've selected only id, Sequelize is retrieving all attributes, from related table as well so I'm getting {id, ... All attributes here}.
How I can prevent this? Sometimes I want to select only 2/3 columns and Sequelize is always selecting all of them what is not efficient.
You can do something like the following
models.modelA.findAll({
attributes: [
'id'
],
raw: true,
include:
[
{
model: models.modelB,
attributes: ['fieldName1', 'fieldName2'], // Add column names here inside attributes array.
required: true
}
]
}).then(function (tenants) {
});
You can try sending empty array as attributes to exclude them:
models.modelA.findAll({
attributes: [
['modelA.id','id']
],
raw: true,
include:
[
{
model: models.modelB,
attributes: [],
required: true
}
]
}).then(function (tenants) {
});

Exclude primary key attributes from a sequelize query

I have a sequelize query from multiple tables inner joined together. I need to group them by on a nested include model but the sequelize query throws the primary key every time, even if I mention the attributes as: attributes:[].
However attributes:[] is working for nested include models.
You can exclude any attributes by passing an exclude array into the attributes option:
MyModel.findAll({
attributes: {exclude: ['some_field']}
});
For included models use attributes: ['prop_name']
Remember include/exclude will not affect nested tables use through: { attributes:[]}
Model.addScope('scope_name', {
attributes: ['id', 'name'],
include: [
{
model: models.role,
as: 'roles',
attributes: ['name'],
through: {
attributes: []
}
}
]
More details can be found here: https://github.com/sequelize/sequelize/issues/4074#issuecomment-153054311
I want to add that you can explicitly list the attributes you want and that they work on nested inner joins as follows:
const my_model = await MyModel.findById(id, {
include: [
{
model: AnotherModel,
attributes: [ 'displayName', 'email' ] // only these attributes returned
},
{ model: YetAnotherModel,
include: [{
model: AnotherModel,
attributes: [ 'id', 'displayName', 'email' ]
}]
}
]
})
Your returned Object should look like:
{
// ...MyModel attributes
,
AnotherModel: {
displayName: '...',
email: '...',
},
YetAnotherModel: {
// ...YetAnotherModel's attributes
,
AnotherModel: {
id: '...',
displayName: '...',
email: '...',
}
}
}

Sequelize include even if it's null

I am using Sequelize express with Node.js as the backend, some data from my sequelize I need to include to another table but some of these data is null so the whole result I’m getting is null.
Question: how can I return some data if data it's available and return the other null if not data is there
router.get("/scheduled/:id", function(req, res, next) {
models.Order.findOne({
where: {
id: req.params.id
},
attributes: ['orderStatus', 'id', 'serviceId', 'orderDescription', 'orderScheduledDate'],
include: [{
model: models.User,
attributes: ['firstName', 'phoneNumber']
}]
}).then(function(data) {
res.status(200).send({
data: data,
serviceName: data["serviceId"]
});
});
});
I want: the result should return null if there is no user for the order and return order details and user when it is null.
However, a where clause on a related model will create an inner join and return only the instances that have matching sub-models. To return all parent instances, you should add required: false for more detail check nested-eager-loading
var users = require('./database/models').user;
models.Order.findOne({
where: {
id: req.params.id
},attributes: ['orderStatus','id','serviceId','orderDescription','orderScheduledDate'],
include: [
{model: users,required: false,
attributes: ['firstName','phoneNumber']
}
]
}).then(function(data) {
res.status(200).send({data : data,serviceName : data["serviceId"]});
});
You can add attribute required: false,
const result = await company.findAndCountAll({
where: conditions,
distinct: true,
include: [
media,
{
model: tag,
where: tagCond,
},
{ model: users, where: userCond, attributes: ['id'] },
{
model: category_company,
as: 'categoryCompany',
where: categoryCond,
},
{ model: media, as: 'logoInfo' },
{ model: city, as: 'city' },
{
model: employee,
as: 'employees',
required: false,
include: [{
model: media,
as: 'avatarInfo',
}],
where: {
publish: {
[Op.ne]: -1,
},
},
},
],
order: [['createdAt', 'DESC']],
...paginate({ currentPage: page, pageSize: limit }),
});

Sequelize Query - Finding records based on many-to-many table and parent table

Given the following sequelize models:
var User = db.define('user', {
name: Sequelize.STRING
});
var Group = db.define('group', {
name: Sequelize.STRING,
public : { type: Sequelize.BOOLEAN, defaultValue: true }
});
Group.belongsToMany(User, { as: 'specialUsers', through: 'user_groups', foreignKey: 'group_id' });
User.belongsToMany(Group, { through: 'user_groups', foreignKey: 'user_id' });
How would I go about finding the Groups for a through the Groups model where the Groups returned should be those where the user has a record in the many to many table -- or -- the group is a public group?
I've tried something like this:
return Group.findAll({
attributes: ['name', 'public'],
include: [{
model: User,
as: 'specialUsers',
where: {
$or : [
{name: 'Neill'},
Sequelize.literal('"group"."public" = true')
]
}
}]
});
return Group.findAll({
attributes: ['name', 'public'],
include: [{
model: User,
as: 'specialUsers',
}],
where: {
$or : {
'$users.name$": 'Neill',
public: true
}
}
});
Should work if you are on a fairly recent version. Note that I moved the where out of the include