Поддерживает ли PostgreSQL параметры сортировки, нечувствительные к акценту?
В Microsoft SQL Server можно указать параметры сортировки" без акцента " (для базы данных, таблицы или столбца), что означает, что это возможно для запроса типа
SELECT * FROM users WHERE name LIKE 'João'
чтобы найти строку с Joao имя.
Я знаю, что можно удалить акценты из строк в PostgreSQL с помощью unaccent_string функция contrib, но мне интересно, поддерживает ли PostgreSQL эти" нечувствительные к акценту " параметры сортировки, поэтому SELECT выше работа.
3 ответов:
используйте модуль unaccent для этого - что совершенно отличается от того, что вы связываете.
unaccent является поиск текста словаря, который удаляет акценты (диакритические знаки) от лексем.
установить один раз на базу данных с:
CREATE EXTENSION unaccent;если вы получаете сообщение об ошибке, как:
ошибка: не удалось открыть файл управления расширением "/usr / share/postgresql / 9.x / extension / unaccent.контроль": Нет такого файла или каталог
установите пакет contrib на сервер базы данных, как указано в этом соответствующем ответе:
среди прочего, он обеспечивает функцию
unaccent()вы можете использовать с вашим примером (гдеLIKEкажется, не необходимый.)SELECT * FROM users WHERE unaccent(name) = unaccent('João');индекс
использовать индекс для такого рода запросов, создать индекс по выражению. , и Postgres принимает только
IMMUTABLEфункции для индексов. Если функция может возвращать другой результат для одного и того же ввода, индекс может молча прерваться.
unaccent()толькоSTABLEнеIMMUTABLEк сожалению,
unaccent()толькоSTABLE, а неIMMUTABLE. Согласно этот нить на pgsql-баги, это из-за три причины:
- это зависит от поведения словарь.
- нет жесткого подключения к этому словарю.
- поэтому он также зависит от текущего
search_path, который может легко измениться.обучение в интернете поручите просто изменить волатильность функции на
IMMUTABLE. Этот метод грубой силы может сломать под ряд условий.другие предлагаю простой
IMMUTABLEфункции-оболочки (как и я сам в прошлом).идет постоянная дискуссия, стоит ли делать вариант с двумя параметрами
IMMUTABLE, который прямо заявляет, использовать словарь. Читайте здесь или здесь.Другой альтернативой был бы этот модуль с неизменный
unaccent()функция Musicbrainz, предоставлено на Github. Не проверял это сам. Я думаю, что я придумал лучшая идея:лучше на данный момент
я предлагаю подход, который по крайней мере так же эффективно, как и другие решения, плавающие вокруг, но безопаснее: Создайте функцию-оболочку с двухпараметрической формой и" жесткой " схемой для функции и словаря:
CREATE OR REPLACE FUNCTION public.f_unaccent(text) RETURNS text AS $func$ SELECT public.unaccent('public.unaccent', ) -- schema-qualify function and dictionary $func$ LANGUAGE sql IMMUTABLE;
publicбудучи схемой, где вы установили расширение (publicпо умолчанию).ранее, я добавил
SET search_path = public, pg_tempк функции-пока я не обнаружил, что словарь также может быть квалифицирован схемой,который в настоящее время (стр. 10) не документирован. Эта версия немного короче и примерно в два раза быстрее в моих тестах на pg 9.5 и pg 10.обновленная версия по-прежнему не позволяет функция inlining потому что функции, объявленные
IMMUTABLEне может называть не неизменяемым функции в теле, чтобы позволить это. Вряд ли имеет значение для производительности при использовании индекс выражение на :CREATE INDEX users_unaccent_name_idx ON users(public.f_unaccent(name));безопасность клиентских программ была усилена с помощью Postgres 10.3 / 9.6.8 и т. д. Ты нужно для определения схемы функции и словаря, как показано при использовании в любых индексах. Смотрите:
- 'словарь "unaccent" не существует записи в журнал postgres, предположительно во время автоматического анализа
адаптировать запросы в соответствии с индексом (так что планировщик запросов может использовать его):
SELECT * FROM users WHERE f_unaccent(name) = f_unaccent('João');вам не нужна функция в правильном выражении. Вы можете поставить безымянные строки, такие как
'Joao'напрямую.лигатур
В Postgres 9.5 и старше лигатуры, такие как' Œ 'или' β', должны быть расширены вручную (Если вам это нужно), так как
unaccent()всегда заменяет один письмо:SELECT unaccent('Œ Æ œ æ ß'); unaccent ---------- E A e a Sвы будете любить это обновление, чтобы unaccent в Postgres 9.6:
расширения
contrib/unaccent'стандарт sunaccent.rulesфайл для обработки всех диакритические знаки, известные в Юникоде, и правильно развернуть лигатуры (Томас Мунро, Леонард Бенедетти)жирным выделено мной. Теперь мы получаем:
SELECT unaccent('Œ Æ œ æ ß'); unaccent ---------- OE AE oe ae ssшаблон соответствие
на
LIKEилиILIKEс произвольными шаблонами, объедините это с модулемpg_trgmв PostgreSQL 9.1 или более поздней версии. Создайте триграмму Gin (обычно предпочтительно) или индекс выражения GIST. Пример для Джина:CREATE INDEX users_unaccent_name_trgm_idx ON users USING gin (f_unaccent(name) gin_trgm_ops);может использоваться для таких запросов, как:
SELECT * FROM users WHERE f_unaccent(name) LIKE ('%' || f_unaccent('João') || '%');индексы GIN и GIST дороже в обслуживании, чем простые дерево:
есть более простые решения для только левых якорных шаблонов. Подробнее о сопоставлении шаблонов и производительности:
pg_trgmтакже предоставляет полезную операторы для "подобия" (%) и "расстояние" (<->).индексы триграмм также поддерживают простые регулярные выражения с
~и соавт. и регистр сопоставление сILIKE:
Я уверен, что PostgreSQL полагается на базовую операционную систему для сортировки. Это тут поддержка создание новых параметров сортировки и настройка параметров сортировки. Хотя я не уверен, сколько работы это может быть для вас. (Может быть довольно много.)
нет, PostgreSQL не поддерживает параметры сортировки в этом смысле
PostgreSQL не поддерживает такие параметры сортировки (нечувствительные к акценту или нет), потому что никакое сравнение не может вернуть равенство, если только вещи не являются двоичными. Это связано с тем, что внутри он будет вводить много сложностей для таких вещей, как хэш-индекс. По этой причине сопоставления в их самом строгом смысле влияет только на заказ и не равенство.
решения
словарь полнотекстового поиска, который не содержит лексем.
для FTS вы можете определить свой собственный словарь с помощью
unaccent,CREATE EXTENSION unaccent; CREATE TEXT SEARCH CONFIGURATION mydict ( COPY = simple ); ALTER TEXT SEARCH CONFIGURATION mydict ALTER MAPPING FOR hword, hword_part, word WITH unaccent, simple;который вы можете затем индексировать с функциональным индексом,
-- Just some sample data... CREATE TABLE myTable ( myCol ) AS VALUES ('fóó bar baz'),('qux quz'); -- No index required, but feel free to create one CREATE INDEX ON myTable USING GIST (to_tsvector('mydict', myCol));теперь вы можете запросить его очень просто
SELECT * FROM myTable WHERE to_tsvector('mydict', myCol) @@ 'foo & bar' mycol ------------- fóó bar baz (1 row)см. также
Unaccent сам по себе.
The
unaccentмодуль может также использоваться сам по себе без FTS-интеграции, для этого проверьте ответ Эрвина
Comments