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'.
Related
I have three models, A, B and C, where:
A.hasMany(B);
B.belongsTo(A);
B.hasMany(C);
C.belongsTo(B);
I'm querying like this:
await A.findOne({
where: { id: id },
include: [
{
model: B,
},
],
});
How can I return the C objects that belongs to B when querying A?
In the end found the solution in the comments of another question.
I need to pass the include with a array like this [{ all: true, nested: true }], I end up having something like this:
await A.findOne({
where: { id: id },
include: [{ all: true, nested: true }],
});
I didn't tested what happens when it loops and also didn't found the docs about it, if a good soul find it feel free to comment it.
Edit:
Nested includes also works:
await A.findOne({
where: { id: id },
include: [
{
model: B,
include: [
{
model: C,
},
],
},
],
});
I have the following database table:
Table: Categories
Columns: id, name, parent_id
and the following records:
1 / Category1 / 0
2 / Category2 / 0
3 / Subcategory1 / 1
4 / Subcategory2 / 1
So I have 2 Categories - Category1 and Category2 and 2 Subcategories of Category1 - Subcategory1 and Subcategory2.
If the parent_id field is 0, that means the record is a Category and if it is not 0 and has the id of another category, then it is a subcategory of that category.
Right now I'm getting all Categories like this:
Category.findAll({
where: {
'parent_id': 0
}
})
.then(result => {
console.log(result)
})
.catch(error => {
console.log(error)
})
but now I also want to somehow include the Subcategories of the Categories as an object property. Right now I'm getting this:
[
{
"id": 1,
"name": "Category1",
"parent_id": 0
}
]
and I want to get something like this:
[
{
"id": 1,
"name": "Category1",
"parent_id": 0,
"subcategories": [
{
"id": 3,
"name": "Subcategory1",
"parent_id": 1,
},
{
"id": 4,
"name": "Subcategory2",
"parent_id": 1,
}
]
}
]
It is similar to eager loading but it is like the model eager loading itself. How can I do this in least queries possible?
You need to use sequelize.define() to create a Model that backs your table, in this case "Category"
// first define your model, you don't have to define the `id` or `parent_id` as they will be created automatically
const Categories = sequelize.define('categories', {
name: {
type: DataTypes.STRING(255),
},
},
{
// use underscores in generated column names
underscored: true,
});
Now create the relationships between parent-<children and child--parent for the Model.
// relate a category to its parent=
Categories.belongsTo(Categories, {
as: 'parent',
foreignKey: 'parent_id',
targetKey: 'id',
});
// relate parent to child categories
Categories.hasMany(Categories, {
as: 'subcategories',
foreignKey: 'parent_id',
});
Now you can use the include option to pass in the Model and specify the as parameter to load the correct relationships. Pass in required: false to use a left join so that results will come back if there are no subcategories.
// ... your code
// now you can include the subcategories and
// pass in the parent_id into the where clause
const category = await Categories.findOne({
include: {
model: Categories,
as: 'subcategories',
required: false,
},
where: {
parent_id: 0,
},
});
// if you know the ID you want is 1...
const category = await Categories.findByPk(1, {
include: {
model: Categories,
as: 'subcategories',
required: false,
},
});
In the reverse direction, from the child to the parent, or in this case both...
// To get a category and its parent and children...
const categoryWithParentAndSubcategories = await Categories.findByPk(123, {
include: [
{
model: Categories,
as: 'parent',
required: false,
},
{
model: Categories,
as: 'subcategories',
required: false,
},
],
});
// you can keep going for multiple levels if you want
// To get a category and its grandparent, parent and children...
const categoryWithParentAndSubcategories = await Categories.findByPk(123, {
include: [
{
model: Categories,
as: 'parent',
required: false,
include: {
model: Categories,
as: 'parent',
required: false,
},
},
{
model: Categories,
as: 'subcategories',
required: false,
},
],
});
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) {
});
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
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 }),
});