Акцентированный поиск в 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, * и ? , с "сбежавшими" версиями.