W trzeciej części cyklu dodaliśmy dane lokalizacyjne oraz informacje o miejscowości, z którego pochodzi auto. Wkrótce potem dodaliśmy również możliwość sortowania po miejscowości, w prosty sposób modyfikując schemę:
<field name="city_sort" type="lowercase" indexed="true" stored="false" /> ... <copyField source="city" dest="city_sort"/>
Okazało się jednak, że sortowanie po miejscowości (pole city_sort) nie funkcjonuje tak jak powinno, a wszystko ze względu na występowanie w nazwach miast polskich znaków. Co z tym zrobić ?
Analiza wymagań
Sprawdźmy, czy faktycznie sortowanie po polu „city_sort” nie uwzględnia polskich znaków. Zadajmy zapytanie:
q=*:*&fl=city&sort=city_sort+asc
Otrzymujemy rezultat:
<result name="response" numFound="6" start="0"> <doc> <str name="city">Białystok</str> </doc> <doc> <str name="city">Koszalin</str> </doc> <doc> <str name="city">Szczecin</str> </doc> <doc> <str name="city">Warszawa</str> </doc> <doc> <str name="city">Świdnik</str> </doc> <doc> <str name="city">Łowicz</str> </doc> </result>
Rzeczywiście, wyniki nie są posortowane poprawnie. Oczekiwaliśmy takiego rezultatu:
<result name="response" numFound="6" start="0"> <doc> <str name="city">Białystok</str> </doc> <doc> <str name="city">Koszalin</str> </doc> <doc> <str name="city">Łowicz</str> </doc> <doc> <str name="city">Szczecin</str> </doc> <doc> <str name="city">Świdnik</str> </doc> <doc> <str name="city">Warszawa</str> </doc> </result>
W celu usprawnienia sortowania danych zawierających polskie znaki wykorzystamy filtr „solr.CollationKeyFilter”.
solr.CollationKeyFilter
Filtr solr.CollationKeyFilter jest wykorzystywany podczas indeksowania, dodając do indeksu specjalne „klucze sortujące”. Pozwala nam na wskazanie kolatora powiązanego z konkretnym krajem i językiem. Możemy również określić „siłę” kolatora, która definiuje pewien minimalny poziom różnic jaki jest brany pod uwagę przy porównywaniu. Przykład:
<filter class="solr.CollationKeyFilterFactory" language="es" country=”ES” strength="primary" />
Powyższy przykład jest definicją fabryki dla filtra solr.CollationKeyFilter, określającego kolator dla języka hiszpańskiego z siłą primary.
Zmiany w schema.xml
- Definicja nowych typów pól:
<fieldType name="polishLowercase" positionIncrementGap="100"> <analyzer> <tokenizer class="solr.KeywordTokenizerFactory"/> <filter class="solr.LowerCaseFilterFactory" /> <filter class="solr.TrimFilterFactory" /> <filter class="solr.CollationKeyFilterFactory" language="pl" country=”PL” strength="primary" /> </analyzer> </fieldType>
Jak widać jest to tak naprawdę definicja już istniejącego typu „lowercase” uzupełnionego o filtr solr.CollationKeyFilter, określającego kolator dla języka polskiego. Będziemy używać tego typu pola do definiowania pól, które zawierają dane z polskimi znakami.
- Zmiana definicji pola „city_sort”:
- zmieniamy typ dla pola „city_sort” na nowo zdefiniowany typ „polishLowercase”:
<field name="city_sort" type="polishLowercase" indexed="true" stored="false" />
Testy funkcjonalności
Zanim przetestujemy, czy zmiana typu pola przyniosła oczekiwany rezultat, pamiętajmy, że filtr solr.CollationKeyFilter wykorzystywany w tym typie działa na etapie indeksacji. Należy zatem wykonać pełną reindeksację danych.
Sprawdźmy teraz wynik zapytania, które wykorzystaliśmy wcześniej do przetestowania jakości sortowania:
q=*:*&fl=city&sort=city_sort+asc
Jak się okazuje, otrzymujemy oczekiwany wcześniej, poprawny rezultat:
<result name="response" numFound="6" start="0"> <doc> <str name="city">Białystok</str> </doc> <doc> <str name="city">Koszalin</str> </doc> <doc> <str name="city">Łowicz</str> </doc> <doc> <str name="city">Szczecin</str> </doc> <doc> <str name="city">Świdnik</str> </doc> <doc> <str name="city">Warszawa</str> </doc> </result>
Podsumowanie
Kolejny zgłoszony problem został pomyślnie rozwiązany. Usprawniliśmy jakość wyników sortowania po polskich znakach, wykorzystując nieskomplikowany, ale jakże pomocny filtr solr.CollationKeyFilter. Czekamy na dalsze zgłoszenia 🙂