Wyszukiwarka fraz z polskimi znakami diakrytycznymi przy użyciu php / mysql

Tworząc w ramach aplikacji webowej wyszukiwarkę treści, spotkałem się z problemem wyszukiwania fraz z polskimi znakami diakrytycznymi (ogonkami). W założeniu napisana w php wyszukiwarka ma zwracać id obiektu (w tym przykładzie notatki), jeżeli w tytule lub treści ma on określony ciąg znaków bez względu na występowanie w nim polskich znaków. Przykładowo fraza “błąd” powinna być odnajdywana zarówno po wpisaniu “błąd” jak i “blad”, ale także “bład” czy “bląd”. W sytuacji odwrotnej, gdy w bazie zapisana jest notatka z frazą bez polskich znaków: “blad”, ma być ona odnajdywana poprawnie po wpisaniu “błąd”, oraz wszystkich wymienionych wyżej wariantów.

O ile problem wydaje się dość złożony, to jego rozwiązanie jest stosunkowo proste. Należy przekazywać do bazy danych frazę pozbawioną przez php polskich znaków i tam porównywać ją z zapisem pozbawionym tych znaków przez mysql. Porównanie odbywa się między dwoma ciągami zawierającymi tylko “zwykłe” znaki, dzięki czemu używanie w zapytaniu polskich ogonków przestaje mieć dla wyniku wyszukiwania jakiekolwiek znaczenie.

Po stronie php funkcja usuwająca ogonki może wyglądać w ten sposób:

 function clearDiacritics($sText) {
 $aReplacePL = array('ą' => 'a', 'ę' => 'e', 'ś' => 's', 'ć' => 'c', 'ó' => 'o', 'ń' => 'n', 'ż' => 'z', 'ź' => 'z', 'ł' => 'l', 'Ą' => 'A', 'Ę' => 'E', 'Ś' => 'S', 'Ć' => 'C', 'Ó' => 'O', 'Ń' => 'N', 'Ż' => 'Z', 'Ź' => 'Z', 'Ł' => 'L');
 return str_replace(array_keys($aReplacePL), array_values($aReplacePL), $sText);
 }

Wykonująca analogiczną operację funkcja mysql:

DELIMITER $$
CREATE FUNCTION `bez_pl_diakrytycznych`(t TEXT) RETURNS TEXT
BEGIN
 SET t = REPLACE(t, 'ą', 'a');
 SET t = REPLACE(t, 'Ą', 'A');
 SET t = REPLACE(t, 'ć', 'c');
 SET t = REPLACE(t, 'Ć', 'C');
 SET t = REPLACE(t, 'ę', 'e');
 SET t = REPLACE(t, 'Ę', 'E');
 SET t = REPLACE(t, 'ł', 'l');
 SET t = REPLACE(t, 'Ł', 'L');
 SET t = REPLACE(t, 'ń', 'n');
 SET t = REPLACE(t, 'Ń', 'N');
 SET t = REPLACE(t, 'ó', 'o');
 SET t = REPLACE(t, 'Ó', 'O');
 SET t = REPLACE(t, 'ś', 's');
 SET t = REPLACE(t, 'Ś', 'S');
 SET t = REPLACE(t, 'ż', 'z');
 SET t = REPLACE(t, 'Ż', 'Z');
 SET t = REPLACE(t, 'ź', 'z');
 SET t = REPLACE(t, 'Ź', 'Z');
 return t;
END
$$
delimiter ;

Aby móc używać funkcji w MySQL, należy ją najpierw dodać do naszej bazy. Wystarczy w tym celu jednokrotnie wydać zapytanie zawierające powyższy kod. Jeżeli wykona się ono poprawnie, funkcja zostanie na stałe umieszczona w bazie i będziemy mogli z niej korzystać przy okazji dowolnego zapytania do bazy danych.

Przykładowe zapytanie do bazy wykorzystujące funkcję usuwającą polskie znaki:

SELECT `note_id`
FROM `note`
WHERE bez_pl_diakrytycznych(
note_body
) LIKE '%błąd%'
OR bez_pl_diakrytycznych(
note_title
) LIKE '%błąd%'
ORDER BY `note_title` ASC
LIMIT 0 , 30;

Leave a Reply

Your email address will not be published. Required fields are marked *