Sequelize case-sensitive queries - node.js

I'm using sequelize and want to know, how to send case-sensitive queries to my DB.
I have table users with a column Login.
And when I send request, (data.Login = '***0xwraith***'), sequelize finds me user with login 0xWraith. But I want the logins 0xWraith and 0xwraith be distinct and separate.
This is the code I use:
let db_user = await db.users.findOne({
where: {
Login: data.login
}
});

MySQL's string comparison is case insensitive by default.
If you would like to have case sensitive query just for this query, you can add BINARY keyword before the comparison to enable it.
SELECT * FROM users WHERE BINARY(`Login`) = '0xWraith';
You can write the query in Sequelize as following.
db.users.findOne({
where: sequelize.where(sequelize.fn('BINARY', sequelize.col('Login')), data.login)
})
If you want to enable the case sensitivity as a table level, read more about it here https://dev.mysql.com/doc/refman/8.0/en/case-sensitivity.html.

Related

Given a mongodb model's array I want to find records in which that array has the most matches using mongoose

I have a mongoose schema as such:
const userSchema = new mongoose.Schema({
keywords: [{ "type": String, "enum": ["yup", "nope"] }],
})
Here, I have one user with a set of keywords and I want to find the records in my database which have the most similar set of keywords to this particular user.
For example, If a user has ["yup" "nope"] as their keywords, I want to find all records of users who have "yup" or "nope" or both in their keywords array. This is just an example and in reality, the users will have a whole lot more keywords to choose from.
How can I do this using mongoose?
I was thinking about one-hot-encoding the values in the array and the records with the most matching 1s can be added to another table "Most similar values table or something" that maintains this list for every user with the user as the foreign key. But I haven't been able to come up with an efficient and/or working algorithm for this yet.
In my opinion the best aproach is regular expresion. I write you one example function how to search and filter data in MongoDB using mongoose. For example lets search customers by lastName example for starts, ends, contains string "yup". Be aware searching with regex is case sensitive default. If you add "i" after regex it will be case insensitive.
async function getCustomers() {
const customers = await Customer
//case search lastName whitch starts with "yup" - case sensitive
.find({lastName: /^yup/})
//or case search lastName whitch ends with "yup" - case insensitive
.find({lastName: /yup$/i })
//or case search lastName whitch contains "yup" in any part
.find({lastName: /.*yup.*/ })
.limit(20) //get top 20 results
.sort({lastName: 1}) // sort by lastName
console.log(customers)}
//searching in array
const customerList = ['Smith', 'Jackson'];
async function getCustomers(arr) {
return await Customer
.find({lastName: {$in: arr}})
.limit(20) //get top 20 results
.sort({lastName: 1}) // sort by lastName
}
getCustomers(customerList);
for more info chceck documentations:
https://docs.mongodb.com/manual/reference/operator/query/regex/

Compare a PostgreSQL Array with a given array in case insensitive way with Node.Js Sequelize?

I am trying to make a generic filter, so it would be great if I could do this one with Sequelize and not with script. What I need is to check if the countries of the user overlaps with the given array. The check should be case insensitive. Is that possible?
const users = await User.findAll({
where: {
countries: { [Op.overlap]: ['GB', 'DE', 'ES'] }
}
});
Here countries column contains array of strings.

OrmLite Contains() not working as expected

If I try to get all users with a certain role like this:
_db.Select<UserAuthCustom>(x => x.Roles.Contains("Bloggers"));
Then it works as expected and returnsthe users.
If I try to do it with the query builder like so:
var q = _db.From<UserAuthCustom>()
.Where(x => x.Roles.Contains("Bloggers"))
.Limit(1);
Then it throws an exception because it thinks "bloggers" is a column and has translated this into into something like WHERE bloggers IN (null).
Is it possible to do something like LIKE '%\"Blogger\"%' on the blobbed field?
You can't use typed queries against blobbed columns like the Roles collection which are blobbed in the table using the configured complex type serializer which defaults to JSV format for all RDBMS's except for PostgreSQL which uses JSON.
If you want to perform server-side queries on the Roles collection I'd recommend persisting them in distinct tables:
container.Register<IAuthRepository>(c =>
new OrmLiteAuthRepository<UserAuthCustom, UserAuthDetails>(c.Resolve<IDbConnectionFactory>()) {
UseDistinctRoleTables = true
});
That way you can use a standard join query to select all users in a specific role:
var q = db.From<UserAuthCustom>()
.Join<UserAuthRole>((u,r) => r.UserAuthId = u.Id)
.Where<UserAuthRole>(x => x.Role == "Bloggers");
Alternatively you would need to create a Custom SQL query to query against the blobbed Roles column as a string, e.g:
q.Where("Roles LIKE #role", new { role = "%Blogger%" });
Or using typed column names in Custom SQL Expressions:
q.Where(q.Column<UserAuthCustom>(x => x.Roles) + " LIKE #role,
new { role = "%Blogger%" });

Log specific postgresql query using pg-promise

I am using pg-promise package with Nodejs to execute PostgreSQL queries. I want to see the queries executed. Only specific queries, say, just one query that I want to debug.
I can see that one recommended way is to use the pg-monitor to catch the events and log them as mentioned here in the examples documentation.
Without using pg-monitor, is there a simple way to just print the prepared query that is executed. I can't see it in the docs.
Example:
db.query("SELECT * FROM table WHERE id = $/id/", {id: 2})
How to print this query to yield?
SELECT * FROM table WHERE id = 2
is there a simple way to just print the prepared query that is executed...
A query in general - yes, see below. A Prepared Query - no, those are by definition formatted on the server-side.
const query = pgp.as.format('SELECT * FROM table WHERE id = $/id/', {id: 2});
console.log(query);
await db.any(query);
And if you want to print all queries executed by your module, without using pg-monitor, simply add event query handler when initializing the library:
const initOptions = {
query(e) {
console.log(e.query);
}
};
const pgp = require('pg-promise')(initOptions);

How to properly escape raw SQL query (plainto_tsquery) in Postgres / node

I'm writing a raw SQL query to implement Postgres full text search in my node backend. I've looked through the official docs, which state:
plainto_tsquery transforms unformatted text querytext to tsquery. The text is parsed and normalized much as for to_tsvector, then the & (AND) Boolean operator is inserted between surviving words.
but I'm not familiar enough with all the different SQL injection techniques to know for certain whether the following will be properly escaped:
'SELECT * FROM "Products" WHERE "catalog_ts_vector" ## plainto_tsquery(\'english\', ' + search_term + ')'
The user will be able to enter whatever search_term they want via the URI.
Do I need to do further escaping/manipulation, or is this functionality fully baked into plainto_tsquery() and other Postgres safeguards?
Edit
As a side note, I plan to strip out most non-alphanumeric characters (including parentheses) with .replace(/[^\w-_ .\&]|\(\)/g, ' '); that should go a long way, but I'm still curious if this is even necessary.
Most likely you're using pg module as PostgreSQL client for node.js. In this case you don't need to worry about sql injection, pg prevents it for you. Just not use string concatination to create query, use parameterized queries (or prepared statement):
var sql = 'SELECT * FROM "Products" WHERE "catalog_ts_vector" ## plainto_tsquery(\'english\', $1)';
var params = [search_term];
client.query(sql, params, function(err, result) {
// handle error and result here
});
Also look at Prepared Statment part of pg wiki and PostgreSQL PREPARE statement.
UPD What about sequelize - it uses pg module by default, but you can specify you preferable pg client in dialectModulePath config parameter (see here). Also you can use parameterized queries in sequelize too. Even better - you can use named parameters. So you code will be:
var sql = 'SELECT * FROM "Products" WHERE "catalog_ts_vector" ## plainto_tsquery(\'english\', :search_term)';
var params = { search_term: search_term }
sequelize.query(sql, Product, null, params).then(function(products) {
// handle your products here
})
Where Product is your sequelize product model.

Resources