Поиск в БД sqlite без учета регистра на русском языке в python
Помогите разобраться с поиском по бд 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 шт):
Автор решения: Viktor
→ Ссылка
Если кому пригодится - вот решение.
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)