Акцентированный поиск в sqlite (android)
У меня есть столбец, в котором некоторые элементы содержат буквы с акцентом.
например: Grambú
Мое требование состоит в том, что когда я ищу "Grambu", я должен получить "Grambú" в результатах.
Для этого требования я попытался использовать параметр "COLLATE NOCASE" для этого конкретного столбца.
Но это не сработало.
Когда я искал решения в Интернете, я нашел много людей, предлагающих нормализовать символы с акцентом
и создание другого столбца на основе этого как единственного варианта.
Есть ли другие более простые решения этой проблемы?
Ответы
Ответ 1
COLLATE NOCASE
работает только для 26 символов верхнего регистра ASCII.
Задайте языковой стандарт базы данных тем, у кого есть поддержка символов с акцентом, используя setLocale()
и используйте COLLATE LOCALIZED
.
Вы также можете попробовать использовать COLLATE UNICODE
.
Но будьте осторожны с этой ошибкой: SQLite UNICODE сортировка, разбитая на ICS - больше не чувствительна к регистру.
Отметьте документацию для упоминания этих двух коллайдеров в Android.
Также ознакомьтесь с этим онлайн-демонстрационным инструментом сопоставления.
Ответ 2
http://www.sqlite.org/lang_expr.html
(ошибка: SQLite понимает только верхний/нижний регистр для символов ASCII по умолчанию. Оператор LIKE по умолчанию чувствителен к регистру для символов Unicode, которые находятся за пределами диапазона ASCII. Например, выражение 'a' LIKE 'A' TRUE, но 'æ' LIKE 'Æ' FALSE.)
Ответ 3
В Android sqlite LIKE
и GLOB
игнорируют как COLLATE LOCALIZED
и COLLATE UNICODE
. Однако есть решение без добавления дополнительных столбцов в таблицу. Как объясняет @asat в этом ответе, вы можете использовать GLOB
с шаблоном, который заменит каждую букву всеми доступными альтернативами этой буквы. В Java:
public static String addTildeOptions(String searchText) {
return searchText.toLowerCase()
.replaceAll("[aáàäâã]", "\\[aáàäâã\\]")
.replaceAll("[eéèëê]", "\\[eéèëê\\]")
.replaceAll("[iíìî]", "\\[iíìî\\]")
.replaceAll("[oóòöôõ]", "\\[oóòöôõ\\]")
.replaceAll("[uúùüû]", "\\[uúùüû\\]")
.replace("*", "[*]")
.replace("?", "[?]");
}
И потом (не буквально так, конечно):
SELECT * from table WHERE lower(column) GLOB "*addTildeOptions(searchText)*"
Таким образом, пользователь, который ищет Grambu или Grambú, преобразует результаты поиска в Gramb [uúùüû], возвращая оба результата.
Важно отметить, что GLOB
игнорирует COLLATE NOCASE
, поэтому я преобразовал все в нижний регистр как в функции, так и в запросе. Также обратите внимание, что функция lower()
в sqlite не работает с не-ASCII-символами, но, вероятно, это те, которые вы уже заменяете!
Функция также заменяет подстановочные знаки GLOB
, *
и ?
, с "сбежавшими" версиями.