LEFT() function extracts a number of characters from a string inside where - mysql

How can build this query?
In the documentation I didn't find any reference to the LEFT function :(
SELECT *
FROM Customers
WHERE
LEFT(CustomerName, 2) = 'An';
to:
await Customers.findOne({
where: {
[fn('left', col('CustomerName'), 2)]: 'An'
}
});
Any idea?

I think you can do:
await Customers.findOne({
where: {
CustomerName: {
[Op.startsWith] : 'An'
}
}
});

Related

Sequelize - query other table inside where clause

I am trying to do something and do not know if this is possible with sequelize. Basically I have this code snippet running on graphQl and basically what this does is to find kits on the kits table and then verify if the same id exists on the "users" table. If not, it returns them, if yes it does not. However now we need to scale this to have pagination and the current snippet is not so scalable. That is why I had the idea to just include the for loop in the where clause or somehow to check there, but really do not know any command on mySql that allows to do this.
Do you have any tip?
async findKitsWithResultNoReg2(_, {search}) {
try {
let promises = []
const a1 = await db.kits.findAll({
where: {
[Op.and]: [
{ result: { [Op.or]: [1, 2, 3] } },
{ cp: 0 },
{[Op.or]: [
{ kitID: { [Op.like]: '%' + search + '%' } }]}
]
}
})
for (let i = 0; i < a1.length; i++) {
const a2 = await db.users.findByPk(a1[i].dataValues.kitID)
if (a2 === null) {
const a3 = {
kitID: a1[i].dataValues.kitID,
result: a1[i].dataValues.result,
date: a1[i].dataValues.resultDate
}
promises.push(a3)
}
}
return Promise.all(promises)
} catch (error) {
console.log(error)
}
},
async findKitsWithResultNoReg() {
try {
const a0 = await sequelize.query(`SELECT kitID, result, resultDate from kits where result in (1,2,3) and cp = 0 and archived = 0 and not Exists(select kitID from users where kits.kitID = users.kitID) order by resultDate desc`, { type: QueryTypes.SELECT })
const a1 = JSON.stringify(a0)
return a1
} catch (error) {
console.log(error)
}
},

Check if an user exist in my database with Node and MySQL [duplicate]

I need to check if entry with specific ID exists in the database using Sequelize in Node.js
function isIdUnique (id) {
db.Profile.count({ where: { id: id } })
.then(count => {
if (count != 0) {
return false;
}
return true;
});
}
I call this function in an if statement but the result is always undefined
if(isIdUnique(id)){...}
I don't prefer using count to check for record existence. Suppose you have similarity for hundred in million records why to count them all if you want just to get boolean value, true if exists false if not?
findOne will get the job done at the first value when there's matching.
const isIdUnique = id =>
db.Profile.findOne({ where: { id} })
.then(token => token !== null)
.then(isUnique => isUnique);
Update: see the answer which suggests using findOne() below. I personally prefer; this answer though describes an alternative approach.
You are not returning from the isIdUnique function:
function isIdUnique (id) {
return db.Profile.count({ where: { id: id } })
.then(count => {
if (count != 0) {
return false;
}
return true;
});
}
isIdUnique(id).then(isUnique => {
if (isUnique) {
// ...
}
});
You can count and find.
Project
.findAndCountAll({
where: {
title: {
[Op.like]: 'foo%'
}
},
offset: 10,
limit: 2
})
.then(result => {
console.log(result.count);
console.log(result.rows);
});
Doc link, v5 Beta Release
I found the answer by #alecxe to be unreliable in some instances, so I tweaked the logic:
function isIdUnique (id, done) {
db.Profile.count({ where: { id: id } })
.then(count => {
return (count > 0) ? true : false
});
}
As Sequelize is designed around promises anyway, alecxe's answer probably makes most sense, but for the sake of offering an alternative, you can also pass in a callback:
function isIdUnique (id, done) {
db.Profile.count({ where: { id: id } })
.then(count => {
done(count == 0);
});
}
}
isIdUnique(id, function(isUnique) {
if (isUnique) {
// stuff
}
});
Extending #Jalal's answer, if you're very conscious about performance implications while maintaining a simple Sequelize structure and you do not need the row data, I suggest you only request one column from the database. Why waste bandwidth and time asking the database to return all columns when you won't even use them?
const isIdUnique = id =>
db.Profile.findOne({ where: { id }, attributes: ['id'] })
.then(token => token !== null)
.then(isUnique => isUnique);
The attributes field tells Sequelize to only request the id column from the database and not sending the whole row's content.
Again this may seem a bit excessive but at scale and if you have many columns that hold a lot of data, this could make a giant difference in performance.
Try the below solution. I tried it and it works well.
const isIdUnique = async (id, model) => {
return await model.count({ where: { id: id } });
};
const checkExistId = await isIdUnique(idUser, User);
console.log("checkExistId: ", checkExistId);

Need help in converting PostgreSQL into mysql in Node.js

Below function I copy it from surveyjs-nodejs repository and looking to achieve this similar into mysql.
function getObjectFromStorage(tableName, callback) {
db.any("SELECT * FROM " + tableName).then(function(result) {
var objects = {};
(result || []).forEach(function(item) {
objects[item.id] = item;
});
callback(objects);
});
}
getObjectFromStorage("surveys", function(objects) {
if (Object.keys(objects).length > 0) {
callback(objects);
} else {
callback(surveys);
}
});
how this .any works?
db
.one("INSERT INTO surveys (name, json) VALUES($1, $2) RETURNING *", [
name,
"{}"
])
.then(callback);
and how this RETURNING * use in mysql?
Thanks

Sequelize - case-insensitive like

How can I achieve this in Sequelize?
SELECT * FROM table where lower(column) LIKE ('abcd%');
I can't find a way to mix lower function with $like
You should use Sequelize.Op :
Table.findAll({
where: {
name: {
[Sequelize.Op.iLike]: searchQuery
}
}
})
Don't forget to add % before or after your searchQuery, if you want to make a partial query.
See the docs here
I found the solution:
Table.findAll({
attributes: ['createdAt', 'col'],
where: {
$and:[
{
createdAt:{
$between:[minDate, maxDate]
}
},
Sequelize.where(
Sequelize.fn('lower', Sequelize.col('col')),
{
$like: 'abcd%'
}
)
]
}
});
If you're using PostGres, you can use the $iLike operator to search rows (NOT column names like your question asks).
Sequelize Docs
While it doesn't fully address your question, hopefully it will help someone down the road who searches for case-insensitive + Sequelize, which brought me here.
Table.findAll({
where: {
createdAt: {
$between: [minDate, maxDate]
},
someOtherColumn: {
$like: '%mysearchterm%'
}
}
})
I run into similar problem and solved by
const values = ['adcd'].map(x => x.toLowerCase());
const results = await SomeModel.findAll({
attributes: [
...Object.keys(SomeModel.rawAttributes),
[Sequelize.fn('LOWER', Sequelize.col('someColumn')), 'lower'],
],
having: { lower: values, },
});

Subquery the same table : Sequelize

I have got a scenario where I would want the below query executed using sequelize.
select * from master where catg_level = 1 and obj_id in (select obj_id from master where catg_level = 2) order by position;
I've the below code written in sequelize.
Master.all({
where: {catg_level: '1'},
order: 'position ASC',
include: [{
model: Master,
as: 'sub-menu',
where: {catg_level: '2'}
}]
})
.then(function(a){
try {
console.log(JSON.stringify(a));
} catch (e) {
console.log(e);
}
});
The SQL generated this
The condition catg_level = 2 is added to the main query instead of being added as a subquery. I understand this is the actual functioning. But is there a workaround to get this done? Please advise.
Thanks in advance.
You can use sequelize.literal:
{
where: {
catg_level: '1',
obj_id:{
in:[sequelize.literal('(select obj_id from master where catg_level = 2)')]
}
},
order: 'position ASC',
}