Поиск в базе данных SQLite без учета регистра русских символов в связке NestJS + TypeORM + SQLite

В принципе это не вопрос, а ответ на него. Хочу поделиться опытом, потому что готового решения я не нашел. Идея - собрать свой драйвер better-sqlite с расширением ICU (International Components for Unicode). Данная БД быстрее SQLite и позволит решить поставленную задачу.

  1. Скачиваем исходный код SQLite - https://sqlite.com/download.html Получаем папку sqlite-amalgamation-хххххх с файлами. В начало файла sqlite3.c пишем -

#define SQLITE_ENABLE_ICU 1

  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.

  1. Скачиваем исходные коды 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
  1. В терминале из папки проекта пишем ‘npm install’. По окончанию все готово!

  2. Немного поправить настройки проекта. В файле 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 {}

  1. Придется пожертвовать удобством 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’])

Удачи!


Ответы (0 шт):