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' },
]
}
});
Related
When using a literal with Sequelize (v4 or v5) you cannot tell Sequelize to cast your value to boolean directly, is it possible to cast it in another way ?
Example :
models.Publication.findAll({
attributes: {
include: [
[models.sequelize.literal("IFNULL((Select 1 from `like` where like.publicationId = `Publication`.`publicationId` and userId = " + req.decoded.userId + "), 0)"), 'liked'],
]
},
order: [['createdAt', 'DESC']],
})
I could use the map function but I have a lot of data and it will slow my function.
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' }
}
})
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 ')
}
I want to implement MySQL full text search with sequelize. The version "sequelize": "^3.23.6". I tried to research about this but could not find =the documentation that guides how to implement this.
Here is the link that says FullText is supported by sequelize:
https://github.com/sequelize/sequelize/issues/2979
But there is not exact documentation on how to do it and how to do a full text search query with sequelize.
Any links advice would be helpful
Thanks !
Since we now have the error message in recent Sequelize that looks like this:
Unhandled rejection Error: Support for literal replacements in the where object has been removed.
The solution would be to provide replacements manually
Payments.findAll({
where: Sequelize.literal('MATCH (SomeField) AGAINST (:name)'),
replacements: {
name: 'Alex'
}
});
Use arrays for more complex conditions:
Payments.findAll({
where: [
{ State: 'Paid' },
Sequelize.literal('MATCH (SomeField) AGAINST (:name)')
],
replacements: {
name: 'Alex'
}
});
Sequelize doesn’t fully support the full-text search feature. We can add a FULLTEXT index as easy as any other index. But operators supporting the MATCH (column) AGAINST (value) syntax haven’t been implemented.
My current solution to the problem consists of creating a regular model:
module.exports = (sequelize, DataTypes) => {
const Book = sequelize.define('Book', {
title: DataTypes.STRING,
description: DataTypes.TEXT,
isActive: DataTypes.BOOLEAN
}, {
indexes: [
// add a FULLTEXT index
{ type: 'FULLTEXT', name: 'text_idx', fields: ['description'] }
]
});
return Book;
};
And using a raw query for querying:
const against = 'more or less';
models.Book.find({
where: ['isActive = 1 AND MATCH (description) AGAINST(?)', [against]]
}).then((result) => {
console.log(result.title);
});
Using only MySQL it's not possible to get correct results if you trying to search for inflectional words, synonyms etc. MySQL developers consider adding dictionaries for full-text search (https://dev.mysql.com/worklog/task/?id=2428), but who knows when we will see it.
If you have to stick with MySQL, I suggest to take a look at Sphinx. It works properly with synonyms and inflectional words.
Since Sequlize does not support for fullText search.
Here is another approach for searching a string from a table
models.sequelize.query(
"SELECT * FROM tableName WHERE CONCAT(field1, '', field2, '', field3, '', field4 ) LIKE \"%" + keyword + "%\"",
{type: models.sequelize.QueryTypes.SELECT}).then(res => {
})
another approach, using single migration file
module.exports = {
up: (queryInterface, Sequelize) => queryInterface.createTable(
'Products',
{
id: {
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV4,
allowNull: false,
primaryKey: true,
},
name: {
type: Sequelize.STRING,
},
},
).then(() => queryInterface.addIndex('Products', ['name'], { type: 'FULLTEXT' })),
down: (queryInterface) => queryInterface.dropTable('Products'),
};
New updated Answer, Here I am searching for Locations that match my searchString.
Location.findAll({
where: {
name: sequelize.where(
sequelize.fn("LOWER", sequelize.col("name")),
"LIKE",
"%" + "You search text here"+ "%". <==== add your searchString Here
),
},
})
I am implementing an application using Sequelize to handle communication with the database.
I have a number of users in the database and I want to implement some search-functionality which allows users to find other users based on their full name.
A user has (amongst other attributes) a firstName and a lastName in its model.
A user who is looking for another user can search for "John Doe", where John is the first name and Doe is the last name.
Unfortunately, the first name and last name are stored in separate fields in my model. Because of this, I need to concatenate the firstName and lastName field in the "where"-clause as I tried below.
In the where-clause I am just concatenating firstName and lastName and then check whether that is "like" the full name that is passed as the argument name. I think the intention of this code below is clear. It is however not working (error says it doesn't expect the '(' after concat so this syntax isn't allowed). Is there an easy trick to do this or should I write my own query using sequelize.query?
var findUserByName = function(name) {
return models.User.find({where: {concat(firstName,' ',lastName): like: name}});
}
This you can try in where clause
where: {
$and: [
Sequelize.where(
Sequelize.fn('concat', Sequelize.col('firstName'), ' ', Sequelize.col('lastName')), {
like: '%'+name+'%'
}
)
]
}
You could do that like this:
User.find({
where: {
$or: [
name: {
$like: ['%', firstName, '%'].join('')
},
lastName: {
$like: ['%', lastName, '%'].join('')
}
]
}).success(function (user) {});