I have these 2 models:
- Orders Models
- Solutions model
Orders Model
'use strict';
const { Model } = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class Orders extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
Orders.hasMany(models.Payments, {
foreignKey: {
name: 'order',
allowNull: false,
},
constraints: false,
onDelete: 'cascade',
});
Orders.hasOne(models.Solutions, {
foreignKey: {
name: 'order',
allowNull: false,
},
constraints: false,
onDelete: 'cascade',
as: "solution"
});
}
}
Orders.init(
{
order_no: {
defaultValue: DataTypes.UUIDV4,
type: DataTypes.UUID,
primaryKey: true,
allowNull: false,
unique: true,
},
order_date: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
title: {
type: DataTypes.STRING,
allowNull: false,
},
},
{
sequelize,
modelName: 'Orders',
tableName: 'Orders',
}
);
return Orders;
};
#2. Solutions table
'use strict';
const { Model } = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class Solutions extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
Solutions.belongsTo(models.Orders, {
foreignKey: 'order',
onDelete: 'cascade',
constraints: false,
as: "solution"
});
}
}
Solutions.init(
{
solutionId: {
defaultValue: DataTypes.UUIDV4,
type: DataTypes.UUID,
primaryKey: true,
allowNull: false,
unique: true,
},
content: {
type: DataTypes.TEXT,
allowNull: false,
},
additional_instruction: {
type: DataTypes.TEXT,
allowNull: true,
},
date_submited: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
},
},
{
sequelize,
modelName: 'Solutions',
}
);
return Solutions;
};
I am trying to get all orders where it’s solution has not been submitted to the solutions table, i.e order field(Foreign key in solution table) is null.
I have tried this
Orders.findAndCountAll({
include: [
{
model: Users,
attributes: ['username', 'email', 'uid'],
},
{
model: Solutions,
as: "solution",
where: {
solutionId: {
[Op.notIn]: Solutions.findAll({
attributes: ['solutionId']
})
}
}
}
],
offset: page,
limit,
})
I was expecting to get a list of all orders where the solutions in the solution table has not been added. Am a bit new to sequelize.
3
Answers
For those coming later to this question, I have come to the conclusion that a LEFT OUTER JOIN between the two tables performs the exact same thing I was looking for. I want to give credit back to @Shengda Liu and @8bitIcon for the solution given. In sequelize the solution would involve just adding the required field in the include statement on the target model to enforce the rule(i.e) find all rows that have an associations in the target associated table. For my case, the solution is as follows.
You can perform a left join with a filter which excludes records from
Solutions
table if theorder
does not exit.You can try to filter after left join, Sequelize can apply where clause directly on the join or after join.
In SQL it’s like :
VS