How can I use current query value in sequelize? - node.js

I am new with sequelize and i need to include multiple table, i try belove:
const result = await product.findAll({
where: {
isDeleted: false,
sellerId
},
attributes: ["name", "type", "isActive", "subCategoryIds"],
include: [
{
model: category,
as: 'categories',
attributes: ["name"],
},
{
model: category,
as: 'subCategories',
attributes: ["name"],
where: {
id: _.split(sequelize.col("subCategoryIds"), ",")
},
},
],
offset: (page - 1) * limit,
limit
});
But it's return error :
SequelizeDatabaseError: operator does not exist: character varying = integer
Product model is:
const product = sequelize.define("products",
{
id: {
type: DataTypes.BIGINT.UNSIGNED,
field: "id",
primaryKey: true,
autoIncrement: true,
index: true,
},
name: {
type: DataTypes.STRING,
field: "name",
allowNull: false,
},
type: {
type: DataTypes.STRING,
field: "type",
allowNull: false,
},
categoryId: {
type: DataTypes.NUMBER,
field: "categoryId",
references: {
key: "id",
model: category,
},
allowNull: false,
},
sellerId: {
type: DataTypes.NUMBER,
field: "sellerId",
references: {
key: "id",
model: user,
},
allowNull: false,
},
subCategoryIds: {
type: DataTypes.STRING,
allowNull: false,
get() {
const result = _.split(this.getDataValue("subCategoryIds"), ",").map(item => +item);
return result;
}
},
isDeleted: {
type: DataTypes.BOOLEAN,
field: "isDeleted",
defaultValue: false,
},
createdAt: {
type: DataTypes.DATE,
field: "createdAt",
defaultValue: DataTypes.NOW,
},
updatedAt: {
type: DataTypes.DATE,
field: "updatedAt",
defaultValue: DataTypes.NOW,
}
}, {
tableName: "products",
timestamps: false
}
);
product.belongsTo(category, { as: "categories", foreignKey: 'categoryId' });
category.hasMany(product, { as: "products", foreignKey: 'categoryId' });
product.belongsTo(category, { as: "subCategories", foreignKey: 'subCategoryIds' });
I am not getting what's going wrong
is there any solution for this
details in table like
categoryId => 11 subCategoryIds => 11, 12
if i remove
{
model: category,
as: 'subCategories',
attributes: ["name"],
where: {
id: _.split(sequelize.col("subCategoryIds"), ",")
},
},
then it's working fine, problem is sequelize.col("subCategoryIds") return string col("subCategoryIds") not the actual value of the subCategories ids 11, 12

Related

multiple inner join at same table sequelize

I'm trying to make a query with multiple joins but when i execute it doesn't work says me
EagerLoadingError [SequelizeEagerLoadingError]: tbl_admon_brands is associated to tbl_admon_vehicles multiple times. To identify the correct association, you must use the 'as' keyword to specify the alias of the association you want to include
I was looking at the documentation of sequalize but i don't understand how can i make a polymorphic association with my models and controllers
Actually i have my getAll like this
const vehicles = await Vehicle.findAll({
attributes: {
include: [
[sequalize.col("brand.name"), "brandName"],
[sequalize.col("brandChassis.name"), "brandChassisName"],
[sequalize.col("brandEnginer.name"), "brandEnginerName"],
/* [sequalize.col("brandBodyWork.name"), "brandBodyWorkName"],
*/ [
sequalize.col("enginePosition.description"),
"enginePositionName",
],
],
},
include: [
{
model: Brand,
as: "brand",
attributes: [],
required: true,
},
{
model: Brand,
as: "brandChassis",
attributes: [],
required: true,
},
{
model: Brand,
as: "brandEnginer",
attributes: [],
required: true,
},
/*{
model: Brand,
as: "engine",
attributes: ['name'],
required: true,
},*/
{
model: Position,
as: "enginePosition",
attributes: [],
required: true,
},
],
where: {
deleted: 0,
},
logging: console.log
});
but when i unomment the line 7 and/or the as engine is when throw me the error.
My model
const { Sequelize } = require("sequelize");
const sequalize = require("../database/database");
const Models = require("./Models");
const Brand = require("./Brand");
const Position = require("./Position");
const Engines = require("./Engines");
const Vehicle = sequalize.define("tbl_admon_vehicles", {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
name: {
type: Sequelize.TEXT,
},
cut: {
type: Sequelize.TEXT,
},
vin: {
type: Sequelize.TEXT,
},
numberEconomic: {
type: Sequelize.TEXT,
},
unitNumber: {
type: Sequelize.INTEGER,
},
brandId: {
type: Sequelize.INTEGER,
},
modelId: {
type: Sequelize.INTEGER,
},
date_acquisition: {
type: Sequelize.DATE,
},
deleted: {
type: Sequelize.INTEGER,
},
brandidchassis: {
type: Sequelize.INTEGER,
},
brandidenginer: {
type: Sequelize.INTEGER,
},
brandidbodywork: {
type: Sequelize.INTEGER,
},
enginepositionid: {
type: Sequelize.INTEGER,
},
typefuelid: {
type: Sequelize.INTEGER,
},
stateplate: {
type: Sequelize.TEXT,
},
federalplate: {
type: Sequelize.TEXT,
},
serie: {
type: Sequelize.TEXT,
},
endorsement: {
type: Sequelize.DATE,
},
unitNumber: {
type: Sequelize.INTEGER,
},
clasificationId: {
type: Sequelize.INTEGER,
},
section: {
type: Sequelize.TEXT,
},
insurerid: {
type: Sequelize.INTEGER,
},
policy: {
type: Sequelize.INTEGER,
},
expedition: {
type: Sequelize.DATE,
},
expiration: {
type: Sequelize.DATE,
},
});
Vehicle.belongsTo(Models, {
foreignKey: "modelId",
as: "model",
});
Vehicle.belongsTo(Brand, {
foreignKey: "brandId",
as: "brand",
});
Vehicle.belongsTo(Brand, {
foreignKey: "brandidchassis",
as: "brandChassis",
});
Vehicle.belongsTo(Brand, {
foreignKey: "brandidenginer",
as: "brandEnginer",
});
Vehicle.belongsTo(Engines, {
foreignKey: "brandidbodywork",
as: "engine",
});
Vehicle.belongsTo(Position, {
foreignKey: "enginepositionid",
as: "enginePosition",
});
module.exports = Vehicle;
my query that i'm trying to do is
SELECT "tbl_admon_vehicles"."id", "tbl_admon_vehicles"."name",
"tbl_admon_vehicles"."cut", "tbl_admon_vehicles"."vin",
"tbl_admon_vehicles"."numberEconomic", "tbl_admon_vehicles"."unitNumber",
"tbl_admon_vehicles"."brandId", "tbl_admon_vehicles"."modelId",
"tbl_admon_vehicles"."date_acquisition", "tbl_admon_vehicles"."deleted",
"tbl_admon_vehicles"."brandidchassis", "tbl_admon_vehicles"."brandidenginer",
"tbl_admon_vehicles"."brandidbodywork", "tbl_admon_vehicles"."enginepositionid",
"tbl_admon_vehicles"."typefuelid", "tbl_admon_vehicles"."stateplate",
"tbl_admon_vehicles"."federalplate", "tbl_admon_vehicles"."serie",
"tbl_admon_vehicles"."endorsement", "tbl_admon_vehicles"."clasificationId",
"tbl_admon_vehicles"."section", "tbl_admon_vehicles"."insurerid",
"tbl_admon_vehicles"."policy", "tbl_admon_vehicles"."expedition",
"tbl_admon_vehicles"."expiration", "tbl_admon_vehicles"."createdAt",
"tbl_admon_vehicles"."updatedAt", "brand"."name" AS "brandName",
"brandChassis"."name" AS "brandChassisName", "brandEnginer"."name"
AS "brandEnginerName", "enginePosition"."description" AS "enginePositionName"
FROM "tbl_admon_vehicles" AS "tbl_admon_vehicles"
INNER JOIN "tbl_admon_brands" AS "brand" ON "tbl_admon_vehicles"."brandId" = "brand"."id"
INNER JOIN "tbl_admon_brands" AS "brandChassis"
ON "tbl_admon_vehicles"."brandidchassis" = "brandChassis"."id"
INNER JOIN "tbl_admon_brands" AS "brandEnginer"
ON "tbl_admon_vehicles"."brandidenginer" = "brandEnginer"."id"
INNER JOIN "tbl_admon_brands" AS "engine"
ON "tbl_admon_vehicles"."brandidbodywork" = "engine"."id"
LEFT OUTER JOIN "tbl_admon_engine_positions" AS "enginePosition"
ON "tbl_admon_vehicles"."enginepositionid" = "enginePosition"."id"
WHERE "tbl_admon_vehicles"."deleted" = 0
I hope someone can helpe or explain me how can i make the polymorphic association

sequelize. Find all posts and add column "isLiked" from table "likes" with boolean value if current user marked this post with 'like'

i have two models:
const Users = sequelize.define('users', {
id: { type: DataTypes.INTEGER, primaryKey: true, unique: true, allowNull: false },
name: { type: DataTypes.STRING, allowNull: false },
role: {
type: DataTypes.STRING,
values: [
'student',
'headman',
'admin'
],
defaultValue: 'student',
allowNull: false
},
avatarImage: {
type: DataTypes.TEXT,
allowNull: false
}
})
and
const Posts = sequelize.define('posts', {
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
title: { type: DataTypes.STRING, allowNull: false },
content: { type: DataTypes.TEXT, allowNull: false },
deadline: { type: DataTypes.DATE, allowNull: false },
postType: {
type: DataTypes.STRING,
values: [
'homework',
'news',
],
defaultValue: 'news', allowNull: false
}
})
boudned by many to many relation through model Likes
const Likes = sequelize.define('likes', {
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
postType: {
type: DataTypes.STRING,
values: [
'homework',
'news',
],
allowNull: false
}
})
//relations
Users.belongsToMany(Posts, {
through: { model: Likes, unique: false },
as: "postsLiked",
foreignKey: "userId",
});
Posts.belongsToMany(Users, {
through: { model: Likes, unique: false },
as: "usersLiked",
foreignKey: "postId",
});
So, i want to get all posts with additional column "isLiked" on each one, with boolean value (true, if user, which makes request, marked this post with 'like'. In other way - false). I don't need all list of users likes this post, just check for one.
So, i have this query in my controller
async getAll(req, res) {
let homeworks = await Posts.findAll({
where: {
postType: 'homework'
},
include: [
{
model: Subjects,
as: 'subject',
attributes: ['id', 'title', 'fullName']
},
{
model: Users,
as: 'usersLiked',
//here i get list of all users likes this post
//if i add propery where (where:{id: user.id}), i get only posts liked by my user
s }
],
})
}
So, can you please help me with this?
//here is the response i have now
//current user.id is 1
{
"id": 2,
"title": "Post 2",
...post fields ...
"subject": {...},
"usersLiked": [
{
"id": 1,
"name": "Max Sobolev",
},
{
"id": 2,
"name": "Albert Cooper",
}
]
},
//what i want to see
{
"id": 2,
"title": "Post 2",
...post fields ...
"subject": {...},
"isLiked": true
},
You can use this method in order to get isLiked field which will true if the user has liked the post and false if not
const gender = await db.SubProduct.findAll(userId && {
attributes: {
include: [
[Sequelize.cast(Sequelize.where(Sequelize.col("likes.userId"), userId), "boolean"), "isLiked"]
],
},
include: [
{ model: db.Like, as: "likes", attributes: [], required: false },
],
group: ['SubProduct.id', 'likes.id']
});
UPDATE 13.04:
So, i found how i can get all posts with "where" property:
i need just use require: false propery
homeworks = await Posts.findAll({
where: {
postType: 'homework',
deadline: {
[Op.gte]: moment()
}
},
include: [
{
model: Subjects,
as: 'subject',
attributes: ['id', 'title', 'fullName']
},
{
model: Users,
as: 'usersLiked',
where: {
id: req.user.id,
},
required: false, // <--- and now i get all posts with empty array 'userLiked' if current user didn't liked this post
}
],
})

Sequelize fetch include data based on alias where condition

I have two tables Employee and Department
Department
const Department = Sequelize.define(
"Department",
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
},
{
underscored: true,
timestamps: true,
paranoid: true,
modelName: "Department",
tableName: "departments",
},
);
Department.associate = function (models) {
// associations can be defined here
models.Department.hasMany(models.Employee, {
foreignKey: "department_id",
as: "employees",
});
};
return Department;
};
Employee
const Employee = Sequelize.define(
"Employee",
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
unique: true,
allowNull: false,
},
status: {
type: DataTypes.STRING,
defaultValue: "active",
},
departmentId: {
type: DataTypes.INTEGER,
},
},
{
underscored: true,
timestamps: true,
modelName: "Employee",
tableName: "employees",
},
);
Employee.associate = function (models) {
models.Employee.belongsTo(models.Department, {
foreignKey: "department_id",
as: "department",
});
};
return Employee;
};
Now I have to fetch the list of employees and putting a filter of department_id = 1
const { departmentId } = req.body;
const employees = await Employee.findAll({
include: [
{
model: Department,
where: {
id: departmentId,
},
},
],
});
I am getting the issue. Department is mapped by association "departments"
Cannot fetch the data.
I found the answer on sequelize docs
const employees = await Employee.findAll({
include: [
{
association: "department", // this is the place to change
where: {
id: departmentId,
},
},
],
});
Learnings:
We will not be able to put association and model together.
We will be able to use the Model if no association is there.
We will be able to use association if there is one.
References: https://sequelize.org/master/manual/eager-loading.html#:~:text=You%20can%20also%20include%20by%20alias%20name%20by%20specifying%20a%20string%20that%20matches%20the%20association%20alias

filter Sequelize belongsToMany

I have the following problem:
I defined my tables (product and collection) like this:
module.exports = (sequelize, type) => {
return sequelize.define('product', {
id: {
type: type.UUID,
primaryKey: true,
defaultValue: type.UUIDV4,
},
title: {
type: type.STRING,
allowNull: false,
},
description: {
type: type.TEXT,
allowNull: false,
},
width: {
type: type.FLOAT,
allowNull: false,
},
height: {
type: type.FLOAT,
allowNull: false,
},
weight: {
type: type.FLOAT,
allowNull: false,
},
length: {
type: type.FLOAT,
allowNull: false,
},
vendor: {
type: type.STRING,
allowNull: false,
},
status: {
type: type.ENUM,
values: ['inactive', 'active'],
defaultValue: 'active',
allowNull: false,
},
})
}
module.exports = (sequelize, type) => {
return sequelize.define('collection', {
id: {
type: type.UUID,
primaryKey: true,
defaultValue: type.UUIDV4,
},
name: {
type: type.STRING,
allowNull: false,
},
image: {
type: type.STRING,
allowNull: true,
},
createdAt: {
type: type.DATE,
allowNull: false,
},
updatedAt: {
type: type.DATE,
allowNull: false,
},
status: {
type: type.ENUM,
values: ['inactive', 'active'],
defaultValue: 'active',
allowNull: false,
},
})
}
Then, I need associated the tables (product and collection) with belongsToMany association and i did it like this:
const ProductModel = require('../api/product/model')
const CategoryModel = require('../api/category/model')
const Product = ProductModel(sequelize, Sequelize)
const Collection = CollectionModel(sequelize, Sequelize)
Product.belongsToMany(Collection, {
through: ProductCollection,
foreignKey: 'productId',
otherKey: 'collectionId',
unique: false,
})
Collection.belongsToMany(Product, {
through: ProductCollection,
foreignKey: 'collectionId',
otherKey: 'productId',
unique: false,
})
Now, i want to get all the products of a collection given by the id sent from the body of the request, i have little time working with sequelize and i donĀ“t know how to do this kind of query.
Can you help me with that?
you can use something like this
let products = Collection.findAll({
where: {
id: collection.id,
},
attributes: ['id', 'name'],
include: [{
model: Product,
through: {
model: ProductCollection,
},
as: 'products',
attributes: ['id', 'title', 'description']
}],
});
return products
hope it helps

Sequelize association generate fields that do no exists

I'm converting a PHP API to a GraphQL api. I'm using Sequelize as ORM package. I have two tables that I want to couple via a hasOne connection.
This is my AdvisoryService model:
module.exports = function(sequelize, DataTypes) {
const AdvisoryService = sequelize.define(
'advisoryService',
{
id: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
autoIncrement: true,
field: 'id',
},
country: {
type: DataTypes.INTEGER(11),
allowNull: true,
references: {
model: 'system_country',
key: 'id',
},
field: 'country',
},
//REDACTED
},
{
tableName: 'advisory_service',
timestamps: false,
},
)
AdvisoryService.associate = models => {
AdvisoryService.hasOne(models.systemCountry, {
as: 'Country',
foreignKey: 'country',
})
}
return AdvisoryService
}
And my systemCountry model:
/* jshint indent: 2 */
module.exports = function(sequelize, DataTypes) {
return sequelize.define(
'systemCountry',
{
id: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
autoIncrement: true,
field: 'id',
},
oldId: {
type: DataTypes.INTEGER(11),
allowNull: true,
unique: true,
field: 'old_id',
},
subcontinentId: {
type: DataTypes.INTEGER(11),
allowNull: true,
references: {
model: 'system_subcontinent',
key: 'id',
},
field: 'subcontinent_id',
},
code: {
type: DataTypes.STRING(2),
allowNull: false,
field: 'code',
},
longCode: {
type: DataTypes.STRING(3),
allowNull: false,
field: 'long_code',
},
currency: {
type: DataTypes.STRING(255),
allowNull: true,
field: 'currency',
},
currencyCode: {
type: DataTypes.STRING(255),
allowNull: true,
field: 'currency_code',
},
isEu: {
type: DataTypes.INTEGER(1),
allowNull: false,
field: 'is_eu',
},
isAsean: {
type: DataTypes.INTEGER(1),
allowNull: false,
field: 'is_asean',
},
isFragileWb: {
type: DataTypes.INTEGER(1),
allowNull: false,
field: 'is_fragile_wb',
},
isFragilePf: {
type: DataTypes.INTEGER(1),
allowNull: false,
field: 'is_fragile_pf',
},
isFragileOecd: {
type: DataTypes.INTEGER(1),
allowNull: false,
field: 'is_fragile_oecd',
},
title: {
type: DataTypes.STRING(255),
allowNull: false,
field: 'title',
},
latitude: {
type: 'DOUBLE',
allowNull: true,
field: 'latitude',
},
longitude: {
type: 'DOUBLE',
allowNull: true,
field: 'longitude',
},
},
{
tableName: 'system_country',
timestamps: false,
},
)
}
It generates the following query:
Executing (default): SELECT `id`, `old_id` AS `oldId`, `subcontinent_id` AS `subcontinentId`, `code`, `long_code` AS `longCode`, `currency`, `currency_code` AS `currencyCode`, `is_eu` AS `isEu`, `is_asean` AS `isAsean`, `is_fragile_wb` AS `isFragileWb`, `is_fragile_pf` AS `isFragilePf`, `is_fragile_oecd` AS `isFragileOecd`, `title`, `latitude`, `longitude`, `country` FROM `system_country` AS `systemCountry` WHERE `systemCountry`.`country` = 1 LIMIT 1;
And throws the following error: SequelizeDatabaseError: Unknown column 'country' in 'field list'. Which I get, because there is no county field in the system_country table. I don't know why the association generates the country field. Can someone point out what I'm doing wrong?
You relation -
AdvisoryService.associate = models => {
AdvisoryService.hasOne(models.systemCountry, {
as: 'Country',
foreignKey: 'country',
})
}
Is defining the relationship with key - country hence its finding country in systemCountry table
Use the Following object in your relation definition -
{as: "Country", foreignKey: "OtherTableColumn", sourceKey: "SameTableColumn"}

Resources