Поиск в БД sqlite без учета регистра на русском языке в python

Рейтинг: 1Ответов: 1Опубликовано: 14.02.2023

Помогите разобраться с поиском по бд sqlite, есть таблица в колонке fullname есть текст типа:

"Аватар / Avatar (2009) BDRip 1080p"

Используя поисковой запрос:

Avatar - бд выводит искомую строку,

avatar - бд выводит искомую строку,

Аватар - бд выводит искомую строку,

аватар - тишина, ответа нет

Что необходимо внедрить в указанный ниже код что бы БД выводила ответ вне зависимости от регистра и языка англ/рус авАтАр аВатаР - без разницы.

import sqlite3
import aiogram

import aiogram.utils
import aiogram.utils.markdown as md

import aiogram.dispatcher

import aiogram.bot
from aiogram.contrib.fsm_storage.memory import MemoryStorage
from aiogram.dispatcher import FSMContext


from aiogram.types import CallbackQuery, ParseMode, Message
from aiogram import Bot, executor, Dispatcher, types


API_TOKEN = ''

# Configure database
conn = sqlite3.connect('ru.db')
conn.row_factory = sqlite3.Row
cursor = conn.cursor()

# Setup bot and dispatcher
bot = Bot(API_TOKEN)
dp = Dispatcher(bot)

@dp.message_handler()
async def process_text_message(message: Message):
        """
        Search books in the database
        """
        search_query = message.text
        cursor.execute("SELECT fullname FROM abooks WHERE fullname COLLATE NOCASE LIKE ?", ('%'+search_query+'%',))
        results = cursor.fetchmany(20)

        if results:
            result_text = 'Results:\n'
            for result in results:
                result_text += result['fullname'] + '\n'
            await bot.send_message(
                chat_id=message.chat.id,
                text=result_text
            )
        else:
            await bot.send_message(
                chat_id=message.chat.id,
                text='No results found.'
            )

if __name__ == '__main__':
    executor.start_polling(dp, skip_updates=True)

Ответы

▲ 1

Если кому пригодится - вот решение.

import re, sqlite3
import aiogram

import aiogram.utils
import aiogram.utils.markdown as md

import aiogram.dispatcher

import aiogram.bot
from aiogram.contrib.fsm_storage.memory import MemoryStorage
from aiogram.dispatcher import FSMContext


from aiogram.types import CallbackQuery, ParseMode, Message
from aiogram import Bot, executor, Dispatcher, types


API_TOKEN = ''

# Configure database
conn = sqlite3.connect('ru.db')
conn.row_factory = sqlite3.Row
cursor = conn.cursor()



def sqlite_like(template_, value_):
    return  sqlite_like_escape(template_, value_, None)

def sqlite_like_escape(template_, value_, escape_):
    re_ = re.compile(template_.lower().
                        replace(".", "\\.").replace("^", "\\^").replace("$", "\\$").
                        replace("*", "\\*").replace("+", "\\+").replace("?", "\\?").
                        replace("{", "\\{").replace("}", "\\}").replace("(", "\\(").
                        replace(")", "\\)").replace("[", "\\[").replace("]", "\\]").
                        replace("_", ".").replace("%", ".*?"))
    return re_.match(value_.lower()) != None    
     
 # Переопределение функции преобразования к нижнему регистру
def sqlite_lower(value_):
    return value_.lower()
       
# Переопределение правила сравнения строк
def sqlite_nocase_collation(value1_, value2_):
    return hash(value1_.decode('utf-8').lower(), value2_.decode('utf-8').lower())
   
# Переопределение функции преобразования к верхнему геристру
def sqlite_upper(value_):
    return value_.upper()


# Setup bot and dispatcher
bot = Bot(API_TOKEN)
dp = Dispatcher(bot)

@dp.message_handler()

async def process_text_message(message: Message):
        
        """
        Search books in the database
        """
        search_query = message.text
        cursor.execute("SELECT fullname FROM abooks WHERE fullname COLLATE NOCASE LIKE '%' || ? || '%'", ('%'+search_query+'%',))
        results = cursor.fetchmany(20)

        if results:
            result_text = 'Results:\n'
            for result in results:
                result_text += result['fullname'] + '\n'
            await bot.send_message(
                chat_id=message.chat.id,
                text=result_text
            )
        else:
            await bot.send_message(
                chat_id=message.chat.id,
                text='No results found.'
            )

if __name__ == '__main__':
    conn.create_collation("BINARY", sqlite_nocase_collation)
    conn.create_collation("NOCASE", sqlite_nocase_collation)
    conn.create_function("LIKE", 2, sqlite_like)
    conn.create_function("LOWER", 1, sqlite_lower)
    conn.create_function("UPPER", 1, sqlite_upper)
    executor.start_polling(dp, skip_updates=True)