Поиск в базе данных SQLite без учета регистра русских символов в связке NestJS + TypeORM + SQLite
В принципе это не вопрос, а ответ на него. Хочу поделиться опытом, потому что готового решения я не нашел. Идея - собрать свой драйвер better-sqlite с расширением ICU (International Components for Unicode). Данная БД быстрее SQLite и позволит решить поставленную задачу.
- Скачиваем исходный код SQLite - https://sqlite.com/download.html Получаем папку sqlite-amalgamation-хххххх с файлами. В начало файла sqlite3.c пишем -
#define SQLITE_ENABLE_ICU 1
- В файле проект packege.json добавляем
{ "scripts": { "preinstall": "npm install better-sqlite3@'^7.0.0' --no-save --build-from-source --sqlite3=\"$(pwd)/sqlite-amalgamation\"" } }
где в —-sqlite3 записываем абсолютный путь к папке sqlite-amalgamation-хххххх.
Так же убедитесь, что из "dependencies" удалено better-sqlite3.
- Скачиваем исходные коды ICU - https://icu.unicode.org/download. Получаем папку icu-release-70-1 (70-1 версия, я эту использовал). Дальше, чтобы компилятор увидел эти файлы я скопировал в папку (для МаcOS)
- /Users/user/Library/Caches/node-gyp/16.14.0/include/node/ все файлы (кроме папок unicode), находящиеся в icu-release-70-1/icu4c/source/i18n и icu-release-70-1/icu4c/source/common
- /Users/user/Library/Caches/node-gyp/16.14.0/include/node/unicode содержимое из пропущенных папок unicode: icu-release-70-1/icu4c/source/i18n/unicode и icu-release-70-1/icu4c/source/common/unicode
В терминале из папки проекта пишем ‘npm install’. По окончанию все готово!
Немного поправить настройки проекта. В файле app.module.ts:
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'better-sqlite3',
database: 'db-name.sqlite',
entities: [],
synchronize: true,
logging: false
})
],
controllers: [AppController],
providers: [AppService], })
export class AppModule {}
- Придется пожертвовать удобством TypeORM. Если бы раньше написали так:
this.filesRepository.find(
{
select: {
keeper: {
lastName: true,
firstName: true,
middleName: true
},
paragraphs: {
period: true
}
},
relations:
{
keeper: true,
paragraphs: true,
},
take: 500,
order: {
id: "DESC"
}
})
То теперь придется написать так (это тоже TypeORM!):
this.filesRepository.createQueryBuilder('files')
.leftJoin('files.keeper', 'keeper')
.leftJoin('files.paragraphs', 'paragraphs')
.select(['files', 'keeper.lastName', 'keeper.firstName', 'keeper.middleName', 'paragraphs.period'])
.orderBy('files.serialNumber', 'DESC')
.take(500)
.getMany()
Сам поиск по полю serialNumber (например):
this.filesRepository.createQueryBuilder('files')
.where(`files.serialNumber Like '%${filters.serialNumber.trim()}%'`)
Или
this.filesRepository.find({
where: {
serialNumber: ILike(`%${filters.serialNumber.trim()}%`),
}
Есть еще небольшие отличия, не относящиеся к данной теме, но упомяну: вместо relations: {joinTable: true} нужно relation([‘joinTable’]) вместо select: {name: true} нужно select([‘name’])
Удачи!