How can we perform following raw query using Sequelize? - mysql

select * from student where totalDays-presentDays > 50;
I m performing this above query using sequelize.
I tried this following code.
where:
{
StudentDB.Sequelize.literal(totalDays-presentDays):
{
[Op.gt]:50
}
}
But It is giving error like Unexpected token '.' in database name and Sequelize keyword.
And I also tried this.
attributes: ['ID', 'Name', 'totalDays','presentDays', [StudentDB.Sequelize.literal('(totalDays - presentDays)'), 'absentDays']],
where:{
absentDays:{
[Op.gt]:50
}
}

Let's say you defined your table name as Student(not variable definition, your definition in model)
So it should look like this:
where: {
and: sequelize.literal('("Student"."totalDays" + "Student"."presentDays" ) > 50 ')
}

Related

How to compare case sensitive string data in Sequelize ORM for express.js?

I want to compare some case sensitive string data using sequelize. my string is "HARSH" and in db, it is "harsh" which should not be equal. I'm using where condition to find the data "HARSH" but in the response, I'm getting string data "harsh".
pReadings.user_model.findAll({
where: {
firstname: "HARSH"
}
})
The collation on the column needs to be ..._bin. It is probably ..._ci, meaning "case insensitive". It was either set that way by default or explicitly.
Please provide SHOW CREATE TABLE for assistance in changing it.
// search case insensitive nodejs usnig sequelize
const sequelize = require('sequelize');
let search = "testData"; // what ever you right here
pReadings.user_model.findAll({
where: {
firstname: sequelize.where(sequelize.fn('LOWER', sequelize.col('firstname')), 'LIKE', '%' + search.toLowerCase() + '%')
}
})
Try using the following,
pReadings.user_model.findAll({
where: sequelize.where(sequelize.fn('BINARY', sequelize.col('firstname')), 'HARSH')
// SELECT * FROM your_table WHERE BINARY(firstname) = 'HARSH';
})
For more information, check out Querying - Sequelize, under heading "Where > Basics". Good luck!
Your query is right. There is no problem with your query.
You could also try:
pReadings.user_model.findAll({
where: {
firstname: { $eq: 'HARSH' }
}
})

Sequelize creating SQL for DATE type

I`m using sequelize with mysql and I want to know if there is a way to use sequelize to create SQLs like these:
SELECT * FROM table WHERE DAY(dateAttribute) = 'chosen_day'
SELECT * FROM table WHERE MONTH(dateAttribute) = 'chosen_month'
I`ve tried to do something like this:
this.test= function () {
let searchingDate = "2017-05%";
return model.table.findAll({
where: {
dateAttribute: searchingDate
}
})
}
This works but it gives a deprecation warning saying that it will be remove in future versions.
Thanks for any help!
Found the solution!
So I used the sequelize.fn() with the Op.and function from sequelize. So the solution was:
this.test = function () {
return model.tableName.findAll({
attributes: ['myAttribute'],
where: {
dateAttribute: {
[sequelize.Op.and]: [
sequelize.where(sequelize.fn('MONTH', sequelize.col('dateAttribute')), 5),
sequelize.where(sequelize.fn('DAY', sequelize.col('dateAttribute')), 5),
]
},
otherAttribute: 'someValue'
}
})
}
This code generated this SQL query:
SELECT myAttribute FROM tableName WHERE (MONTH('dateAttribute') = 5 AND DAY('dateAttribute') = 5) AND otherAttribute = 'someValue'
I hope to save you guys from doing this long researching that I made!
Remember be HAPPY!

Sequelize: Concat fields in WHERE LIKE clause

I am using the sequelize ORM for a node.js project I am working on. One query I have, I need to perform a like operation on the concatenated result of multiple columns.
For instance, something like the following:
SELECT * FROM People WHERE (CONCAT(firstname, ' ', lastname)) LIKE '%John Do%'.
I am using the following syntax and would like to know if this is possible without having to resort to using RAW queries (which is nowhere else in my solution).
var criteria = {
include: [
occupation
],
where: {
is_active: 1
},
nest: false
};
db.people.findAll(criteria, {}).then(function(people) {
success(people);
}).catch(function(err) {
error(err);
});
Any ideas?
You'll need something like this
var criteria = {
where: Sequelize.where(Sequelize.fn("concat", Sequelize.col("firstname"), Sequelize.col("lastname")), {
like: '%John Do%'
})
}
Note: untested
Original source
Inspired by #code-jaff but you need to concatenate a space string in between first and last names to make this work correctly. Otherwise it would only return for 'JohnDoe' and not for 'John Doe'. Here's the code.
Sequelize.where(Sequelize.fn('concat', Sequelize.col('firstName'), ' ', Sequelize.col('lastName')), {
like: '% John Doe %'
})
To provide some context for people who might not understand where this would fit into your query, this is an example of the above code in a where or statement. req.body.query being the variable search term that you're POSTing.
Users.findAll({
where: {
$or: [
Sequelize.where(Sequelize.fn('concat', Sequelize.col('firstName'), ' ', Sequelize.col('lastName')), {
like: '%' + req.body.query + '%'
}),
{ email: { $like: '%' + req.body.query + '%' } },
{ companyName: { $like: '%' + req.body.query + '%' } }
]
}
})
Update for Sequelize 4.0
String based operators ($like and $or in the above example) have been deprecated in favour of symbol based operators. It's a good thing for security
See: http://docs.sequelizejs.com/manual/tutorial/querying.html#operators
These operators would be replaced with [Sequelize.Op.like] and [Sequelize.Op.or]. There are also other ways to configure it in your sequelize options highlighted in their documentation
I was able to achieve this with the new sequelize version 5.21.13 based on #yjimk answer.
Users.findAll({
where: {
[sequelize.Op.or]:{
namesQuery: sequelize.where(
sequelize.fn(
"concat",
sequelize.col("firstName"),
" ",
sequelize.col("lastName")
),
{
[sequelize.Op.like]: `%${req.body.query}%`,
}
),
email: {[sequelize.Op.like]: `%${req.body.query}%`},
companyName: {[sequelize.Op.like]: `%${req.body.query}%`},
}
})
db.models.users.findOne({
where: {
[db.sequelize.Op.and]: [
db.sequelize.where(
db.sequelize.fn('CONCAT', db.sequelize.col('first_name'), ' ', db.sequelize.col('last_name')),
{ like: `%${name}%` },
),
{ status: 'ACTIVE' },
]
}
});

Convert Mysql query to Mongodb find()

I have a mongodb collection structured like this:
{ "client" : "CLIENTIDHERE", "amount" : 90, "invoice": "SOMEIDHERE", "date" : ISODate("2014-07-09T11:13:49.273Z") }
And need to select somehow all the payments made from a client.
In mysql I would do something like this, but with mongodb I have really no clue.
SELECT SUM(amount) payments,client FROM invoices GROUP BY client;
What I tried:
db.invoices.find({
$group: {
amount: {$sum: "$amount"}
}
}, {
$project:{
amount: "$amount",
client: "$client"
}
})
But it didn't work. What did I do wrong?
EDIT: I get the following error:
error: { "$err" : "Unsupported projection option: amount", "code" : 13097 }
Your $group step doesn't define what to GROUP BY. MongoDB's equivalent for the SQL GROUP BY is the _id field of the $group statement which is missing from your query. Also, when you want to use aggregation, you need to use .aggregate( instead of .find(.
db.invoices.aggregate({
$group: {
_id: "$client",
amount: { $sum: "$amount"}
}
});
This will write the client into the _id field. When you would rather want to have the field named client, you can fix that in the $project step, but otherwise the projection is not required in this case.

Specifying specific fields with Sequelize (NodeJS) instead of *

Alright so I have a project in NodeJS where I'm utilizing Sequelize for a MySQL ORM. The thing works fantastically however I'm trying to figure out if there is a way to specify what fields are being returned on a query basis or if there's even a way just to do a .query() somewhere.
For example in our user database there can be ridiculous amounts of records and columns. In this case I need to return three columns only so it would be faster to get just those columns. However, Sequelize just queries the table for everything "*" to fulfill the full object model as much as possible. This is the functionality I'd like to bypass in this particular area of the application.
You have to specify the attributes as a property in the object that you pass to findAll():
Project.findAll({attributes: ['name', 'age']}).on('success', function (projects) {
console.log(projects);
});
How I found this:
The query is first called here: https://github.com/sdepold/sequelize/blob/master/lib/model-definition.js#L131
Then gets constructed here: https://github.com/sdepold/sequelize/blob/master/lib/connectors/mysql/query-generator.js#L56-59
Try this in new version
template.findAll({
where: {
user_id: req.params.user_id
},
attributes: ['id', 'template_name'],
}).then(function (list) {
res.status(200).json(list);
})
Use the arrays in the attribute key. You can do nested arrays for aliases.
Project.findAll({
attributes: ['id', ['name', 'project_name']],
where: {id: req.params.id}
})
.then(function(projects) {
res.json(projects);
})
Will yield:
SELECT id, name AS project_name FROM projects WHERE id = ...;
All Answers are correct but we can also use include and exclude as well
Model.findAll({
attributes: { include: ['id'] }
});
Model.findAll({
attributes: { exclude: ['createdAt'] }
});
Source