Support accent-insensitive matching using the sqlean sqlite3 unicode extension

This commit is contained in:
mikiher 2024-07-27 21:56:07 +03:00
parent 6c379fc3a7
commit dedf6e5d4b
4 changed files with 75 additions and 39 deletions

View file

@ -207,6 +207,7 @@ class Database {
try {
await this.sequelize.authenticate()
await this.loadExtensions([process.env.SQLEAN_UNICODE_PATH])
Logger.info(`[Database] Db connection was successful`)
return true
} catch (error) {
@ -215,6 +216,30 @@ class Database {
}
}
async loadExtensions(extensions) {
// This is a hack to get the db connection for loading extensions.
// The proper way would be to use the 'afterConnect' hook, but that hook is never called for sqlite due to a bug in sequelize.
// See https://github.com/sequelize/sequelize/issues/12487
// This is not a public API and may break in the future.
const db = await this.sequelize.dialect.connectionManager.getConnection()
if (typeof db?.loadExtension !== 'function') throw new Error('Failed to get db connection for loading extensions')
for (const ext of extensions) {
Logger.info(`[Database] Loading extension ${ext}`)
await new Promise((resolve, reject) => {
db.loadExtension(ext, (err) => {
if (err) {
Logger.error(`[Database] Failed to load extension ${ext}`, err)
reject(err)
return
}
Logger.info(`[Database] Successfully loaded extension ${ext}`)
resolve()
})
})
}
}
/**
* Disconnect from db
*/
@ -801,6 +826,23 @@ class Database {
Logger.warn(`Removed ${badSessionsRemoved} sessions that were 3 seconds or less`)
}
}
normalize(value) {
return `lower(unaccent(${value}))`
}
async getNormalizedQuery(query) {
const escapedQuery = this.sequelize.escape(query)
const normalizedQuery = this.normalize(escapedQuery)
const normalizedQueryResult = await this.sequelize.query(`SELECT ${normalizedQuery} as normalized_query`)
return normalizedQueryResult[0][0].normalized_query
}
matchExpression(column, normalizedQuery) {
const normalizedPattern = this.sequelize.escape(`%${normalizedQuery}%`)
const normalizedColumn = this.normalize(column)
return `${normalizedColumn} LIKE ${normalizedPattern}`
}
}
module.exports = new Database()