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

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
})

Related

How to do this request using sequelize?

I would like to know the code to write to execute this request using sequelize:
select * from "Songs"
where Id in (
select "songId" from "Likes"
where "userId"=1
)
I finaly found by myself how to do it, here is my code :
const songs = await models.Songs.findAll({
attributes: ['id', 'title', 'imageUrl', 'nbListening'],
where: {
id: {
[Op.in]: sequelize.literal(
`(select "songId" from "Likes" where "userId"=${req.user.id})`
),
},
},

Sequelize function on where

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,
}),
],
},
});

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

Why my conditional WHERE inside the OR operator in the Sequelize query is converted to AND?

I'm trying to make a query with Sequelize with a conditional WHERE like explained here (How to perform a search with conditional where parameters using Sequelize).
The relevant part of my code is like this
const Op = Sequelize.Op;
var search = {};
if (typeof req.query.search !== 'undefined'){
search.nome = {[Op.like]: '%' + req.query.search + '%'};
search.username = {[Op.like]: '%' + req.query.search + '%'};
}
model.User.findAll({
where:{
[Op.or]: [
search
]
})
It works, but the generated SQL adds an AND instead of an OR, like this:
SELECT 'id_', 'nome', 'username', 'id' FROM 'User' AS 'User' WHERE (('User'.'nome' LIKE '%test%' AND 'User'.'username' LIKE '%test%'))
Am I doing something wrong that I fail to see?
I've already tried several combinations of this and none works.
There is something wrong in the constructed search filter. [Op.or] should be the spread of search not an array.
Try as below,
model.User.findAll({
where: {
[Op.or]: {
email: {
[Op.like]: 'abcd',
},
username: {
[Op.like]: 'cdf',
},
}
},
logging: console.log,
});
you will get the below,
SELECT "id", "name", "username" FROM "users" AS "User" WHERE "User"."deleted_at" IS NULL AND ("User"."email" LIKE 'abcd' OR "User"."username" LIKE 'cdf');
try to use spread
model.User.findAll({
where: {
[Op.or]: [
{...search}
]
}
})
what about this?
const where = {}
if (typeof req.query.search !== 'undefined'){
where[Op.or] = {
nome : {
[Op.like] : `%${req.query.search}%`
},
username : {
[Op.like] : `%${req.query.search}%`
},
}
}
model.User.findAll({
where
})
Here's some code I'm using:
return Models.job.findAndCountAll({
raw: true,
where: {
isActive: 1,
...((args.statusOfJob > 0) && {
status: args.statusOfJob
})
}
})
In this case, statusOfJob is a numerical value used in a select object, where 0 would show all items.
It's a bit cryptic, but it's also concise and reduces the need for extraneous conditional statements and assignments.

How to make if condition in Nodejs Sequelize model query

I'm trying to use if condition in Nodejs Sequelize query using models.
I want to select users by filter parameter if there is filter parameter. If there isn't I want to select all users.
I did that in the following way, but I hardcoded this:
var filterData = { id: { $ne: null} };
Is there a proper way to do that using Sequelize? Thanks.
function getData(id, filter='') {
var filterData = { id: { $ne: null} };
if (filter !== '') {
filterData = {
$or: [
{firstName: {$like: '%' + filter + '%'}},
{lastName: {$like: '%' + filter + '%'}}
]
};
}
return models['Profile'].findAll({
where: { profileId: id },
include: [{
model: models.Profile.scope('essentials'),
where: filterData,
as: 'entity'
}]
})
}
I assume you've tried var filterData = {} or var filterData = true and that didn't work? If so, one other option would be to build your include object beforehand, and then add the where clause to it conditionally:
function getData(id, filter='') {
var includeObj = {
model: models.Profile.scope('essentials'),
as: 'entity'
}
if (filter !== '') {
includeObj.where = {
$or: [
{firstName: {$like: '%' + filter + '%'}},
{lastName: {$like: '%' + filter + '%'}}
]
};
}
return models['Profile'].findAll({
where: { profileId: id },
include: [includeObj]
})
}
That avoids the awkward "where ID not equal to null" condition.
Also a small side note (and maybe you already know this and just prefer the more explicit code) but since empty string is falsey in javascript,
if (filter !== '') {
can be replaced with just
if (filter) {
where: {
[Op.and]: [
req.query.gigType && { gigType: req.query.gigType },
],
},
You can just use it like this. This is not the answer to your question. But you can get an idea of how to write this. if there is req.query.gigType variable, giType = req.query.gigType filter applied. If not, the filter doesn't apply.

Resources