Sequelize function on where - node.js

I using sequelize 5.21.2 on Node 12.
I want to get like this:
SELECT `id`
FROM `order`
WHERE (substr(`order`.`code`,1,8) >= '20200101'
AND substr(`order`.`code`,1,8) <= '20201230')
So I wrote it like this:
return Model.order.findAll({
attributes: [
'id',
],
where: {
[sequelize.fn('substr', Model.sequelize.col('code'), 1, 8)]: {
[Op.gte]: params.start_date,
[Op.lte]: params.end_date,
},
},
});
But It returns:
SELECT `order`.`id`
FROM `order`
WHERE (`order`.`[object Object]` >= '20200101'
AND `order`.`[object Object]` <= '20201230')
I tried
[sequelize.literal('STR_TO_DATE(substr(code,1,8),\'%Y %m %d\')'), 'order_date']
[sequelize.literal('STR_TO_DATE(substr(code,1,8),\'%Y %m %d\')')]
[sequelize.fn('substr', Model.sequelize.col('code'), 1, 8)]
but they work fine when I SELECT, but not WHERE.
How do I get the results I want? I couldn't find any relevant information in the official manual.. (https://sequelize.org/v5/manual/querying.html#where)

Use sequelize.where and Op.and to generate the select statement using a function and not a column. See this page in the Sequelize documentation - Advanced queries with functions (not just columns)
const { sequelize, order } = Model;
return order.findAll({
attributes: [
'id',
],
where: {
[Op.and]: [
sequelize.where(sequelize.fn('substr', sequelize.col('code'), 1, 8), {
[Op.gte]: params.start_date,
}),
sequelize.where(sequelize.fn('substr', sequelize.col('code'), 1, 8), {
[Op.lte]: params.end_date,
}),
],
},
});

Related

Typeorm relations query builder

I have a little problem figuring out how to get data from a linked table using queryBuilder
Currently i have this code:
const users = await databaseConntection
.getRepository(User)
.createQueryBuilder("user")
.select(["images.author_id", "user.id", "user.username"])
.leftJoinAndSelect(
(queryBuilder) =>
queryBuilder
.select(["title", "updated_at", "author_id"])
.from(Image, "image")
.orderBy({ updated_at: "ASC" })
.take(5),
"images",
"images.author_id = user.id"
)
.andWhere("username LIKE :profile")
.setParameters({
profile: `%${profile}%`,
})
.groupBy("images.author_id")
.take(limit)
.skip(page * limit - limit)
.getRawMany();
Current result:
column "user.id" must appear in the GROUP BY clause or be used in an aggregate function
Expected result:
[
{
"id": 1,
"username": "some username",
"images": [
{
"title": "some image title",
"updated_at": "2021-05-21T03:49:44.299Z",
"author_id": 1
}
...rest 4 images
]
}
...rest users
]
How i can achieve this result using query builder?
Thanks for any helping.
I don't know what is wrong with my code, but i was migrate to prisma orm, and he work like as expected.
Here the code using prisma orm, and this return the expected result (without ids):
const users = await prisma.user.findMany({
where: {
username: {
contains: profile as string,
},
},
select: {
username: true,
images: {
select: {
title: true,
updated_at: true,
},
orderBy: {
updated_at: "asc",
},
take: 5,
},
},
take: limit,
skip: page * limit - limit,
});

Sequelize ORM return a weird response after inner join tables in nodejs

I use sequelize orm to manage my data base (mysql).
I make a inner join that work good but the problem that the table that join return a weird variable.
this is my code
const getReports = id => {
return new Promise((resolve, reject) => {
models.Report.findAll({
where: { companyID: [513603324, 515490704, 511493827] },
include: [{
model: models.Reports_type,
attributes:["name"],
required: true
}],
raw: true
})
.then(result => {
resolve(result);
})
.catch(err => {
reject(err);
});
});
};
The output is
[
{
"id": 8,
"creatorUserID": 1,
"currentUserEditorID": 1,
"companyID": 511493827,
"stageID": 1,
"scenarioID": 1,
"typeID": 1,
"year": 2020,
"deadLine": "2019-10-30T22:00:00.000Z",
"createdAt": "2019-10-29T08:31:19.000Z",
"updatedAt": "2019-10-29T08:31:19.000Z",
"Reports_type.name": "excelent",
"companyName": "energy",
}
]
The problem is i get it weird like this:
"Reports_type.name"
I want the output be:
"name"
This topic has been covered before - see this.
To avoid the prefix, attributes must be specified in the main model rather than the included model. The example below should produce all fields in Report plus Reports_type.name. Note: the alias of Reports_type may be a little different than I've guessed - if you get a "field does not exist", find the correct alias from the generated SQL.
models.Report.findAll({
where: { companyID: [513603324, 515490704, 511493827] },
include: [{
model: models.Reports_type,
attributes:[], // suppress here
required: true
}],
raw: true,
attributes: {
include: [[Sequelize.col("reports_types.name"), "name"]] // include here; table alias may be a little different!
}
})

How to convert postgreSQL to Sequelize format

I have to try to convert my postgre sql query to orm concept using sequelize npm package, kindly guide me.
select * from "locationDepartmentMappings" as a
inner join "departments" as b on a."departmentId" = b.id
inner join "locations" as c on a."locationId" = c.id
where (
b."departmentName" like '%Accounting%' or c."locationName" like '%Accounting%'
)
limit 1;
As per below code still i have getting
error: column locationDepartmentMapping.department.departmentName does not exist
As #shivam mentioned i have tried depends mine below, can you what i need to changes,
let ldv = await LocationDepartmentModel.findAll({
include: [
{
model: LocationModel,
as: "location",
required: true,
},
{
model: DepartmentModel,
as: "department",
required: true,
}
],
where: {
$or: [
{
"department.departmentName": { like: `%${reqQueryName}%` }
},
{ "location.locationName": { like: `%${reqQueryName}%` } }
]
},
limit:1
});
Sequelize has pretty good documentation on how to write queries using the orm syntax.
To start with, the above query would look something like
Model.locationDepartmentMappings.findAll({
include: [
{
model: Model.departments
where: {departmentName: {$like: '% Accounting%'}}
},
{
model: Model.locations
where: {locationName: {$like: '% Accounting%'}}
}],
limit: 1
})
What you should consider getting to above query is
1. Learn how to create sequelize models
2. Learn Associations
3. Querying
There are a lot of great tutorials out there, which can help you get started, and are just a google search away!
Final with help got the solutions :
let ldData = await LocationDepartmentModel.findAll({
include: [
{
model: LocationModel,
as: "location",
required: true
},
{
model: DepartmentModel,
as: "department",
required: true
}
],
where: {
$or: [
{ "$department.departmentName$": { like: `%${reqQueryName}%` } },
{ "$location.locationName$": { like: `%${reqQueryName}%` } }
]
},
limit: 1
});
Courtesy for below :
#shivam answer for joining tables
#ManjulSigdel answer for where condition include table column

How to run AND and Or operator with Sequelize in Node.js

I am new to Node.js, am trying to run a 'And' and 'OR' operator in Sequelize, the MySQL query is this
SELECT * from User WHERE (role = 'INSTRUCTOR') AND ((pix <> null) OR (description <> null)) OEDER BY id DESC
The above MySQL query is what I want to run with Sequelize but it didn't work.
Below is my Sequelize code:
return await models.User.findAll({
where: {role: 'INSTRUCTOR'}, [Op.or]: [{pix: {[Op.ne]: null}}, {description: {[Op.ne]: null,}}], order: [['id', 'DESC']]
})
How can I run that query in Sequelize?
Formatting the code can sometimes help ...
Seems you had a misplaced }
return await models.User.findAll({
where: {
role: { [Op.eq]: 'INSTRUCTOR' },
[Op.or]: [
{ pix: { [Op.ne]: null} },
{ description: { [Op.ne]: null } }
]
},
order: [ ['id', 'DESC'] ]
})

Sequelize WHERE sequelize.fn(...) AND something='something' ordering issue

I have a Sequelize findOne function that looks to select a row where the given point intersects a polygon (col 'geom') AND status = 'active'.
var point = sequelize.fn('ST_GeomFromText', 'POINT(' + lng + ' ' + lat +')', 4326);
var intersects = sequelize.fn('ST_Intersects', sequelize.col('geom'), point);
GeoCounty.findOne({
attributes: ['id', 'name' ],
where: {
status: 'active',
$and: intersects
},
plain: true
})
As of right now, it works just fine. It produces SQL that looks like:
SELECT "id", "name" FROM "geocounty" AS "geocounty" WHERE "geocounty"."status" = 'active' AND (ST_Intersects("geom", ST_GeomFromText('POINT(-98.025006 43.714735)', 4326))) LIMIT 1;
What I really want is:
SELECT "id", "name" FROM "geocounty" AS "geocounty" WHERE (ST_Intersects("geom", ST_GeomFromText('POINT(-98.025006 43.714735)', 4326))) AND "geocounty"."status" = 'active' LIMIT 1;
which is to say the ST_Intersects clause comes first and the AND status='active' comes after.
My questions are:
1. Is there any sort of performance penalty for executing the query the first way which does work?
2. Is there a way to structure a where clause like this in Sequelize?
This does not work:
GeoCounty.findOne({
attributes: ['id', 'name' ],
where: {
intersects,
$and: {
status: 'active'
}
},
plain: true
})
It produces this SQL:
SELECT "id", "name" FROM "geocounty" AS "geocounty" WHERE "geocounty"."intersects" = ST_Intersects("geom", ST_GeomFromText('POINT(-98.025006 43.714735)', 4326)) AND ("geocounty"."status" = 'active') LIMIT 1;
There is no geocounty.intersects...
i stumbled over this post while searching for a similar problem and found a solution for me, that might help you with #2.
I wrapped the function call into an extra where. My code looks like this (works in NodeJs 10.9.0, Sequelize 4.38.0 on a MariaDB):
Cat.findOne({
where: {
color: 'red',
$and: sequelize.where(sequelize.fn('char_length', sequelize.col('cat_name')), 5)
}
});
SELECT id, cat_name, color FROM cat_table WHERE color = 'red' AND char_length(cat_name) = 5;
On your example it would look like this (not tested):
var intersects = sequelize.fn('ST_Intersects', sequelize.col('geom'), point);
GeoCounty.findOne({
attributes: ['id', 'name' ],
where: {
$and: sequelize.where(intersects, 1),
status: 'active'
},
plain: true
})

Resources