Zapytania wildcard i jak wygląda ich obsługa w Solr

Jeden z naszych czytelników zgłosił bardzo ciekawy problem, który można streścić do następującego pytania – „Dlaczego nie działają mi polskie litery z zapytaniach z wykorzystaniem wildcardów ?„. Ten wpis postara się odpowiedzieć na to pytanie.

Definicja typu i pola

Nasz czytelnik posiada następujący typ danych opisanych w pliku schema.xml:

<fieldType name="c_string" class="solr.TextField">
 <analyzer type="index">
  <tokenizer class="solr.KeywordTokenizerFactory"/>
  <filter class="solr.ASCIIFoldingFilterFactory"/>
  <filter class="solr.LowerCaseFilterFactory" />
  <filter class="solr.ReversedWildcardFilterFactory" />
 </analyzer>
 <analyzer type="query">
  <tokenizer class="solr.KeywordTokenizerFactory"/>
  <filter class="solr.ASCIIFoldingFilterFactory"/>
  <filter class="solr.LowerCaseFilterFactory" />
  <filter class="solr.ReversedWildcardFilterFactory" />
 </analyzer>
</fieldType>

Do tego pole, które jest obsługiwane przez ten typ wygląda następująco:

<field name="word" type="c_string" indexed="true" stored="true" />

Dane

Do testów opisywanego problemu wykorzystywałem następujące dane:

<add>
 <doc>
  <field name="id">1</field>
  <field name="word">Zażółć gęślą jaźń</field>
 </doc>
</add>

Definicja problemu

Problem został zdefiniowany następująco: „w polu word mam polskie znaki, ale gdy zrobię zapytanie z polskim znakiem, np. „word:*ą*” to nic mi nie znajdzie„.

O czym warto pamiętać korzystając z ReversedWildcardFilterFactory

Podczas korzystania z ReversedWildcardFilterFactory należy pamiętać, aby filter ten zdefiniować tylko dla analizy podczas indeksowania, a nie definiować go dla analizy zapytań. Zatem poprawiona definicja typu powinna wyglądać następująco:

<fieldType name="c_string" class="solr.TextField">
 <analyzer type="index">
  <tokenizer class="solr.KeywordTokenizerFactory"/>
  <filter class="solr.ASCIIFoldingFilterFactory"/>
  <filter class="solr.LowerCaseFilterFactory" />
  <filter class="solr.ReversedWildcardFilterFactory" />
 </analyzer>
 <analyzer type="query">
  <tokenizer class="solr.KeywordTokenizerFactory"/>
  <filter class="solr.ASCIIFoldingFilterFactory"/>
  <filter class="solr.LowerCaseFilterFactory" />
 </analyzer>
</fieldType>

Czy teraz już działa ?

Zadając następujące zapytanie:

http://localhost:8983/solr/select?q=word:*ś*

dalej nie otrzymujemy żadnych wyników. Dlaczego ?

Solr i obsługa wildcardów

Odpowiedź na pytanie postawione powyżej, jest dość prosta – Solr nie analizuje zapytań w których występują wildcardy. Tak, oznacza to, że podczas indeksacji filtr ASCIIFoldingFilterFactory usuwa nam polskie znaki zamieniając je na ich odpowiedniki z tablic 127 znaków ASCII, jednak w trakcie zadawania zapytania to się nie dzieje, pomimo tego, że filtry są zdefiniowane prawidłowo. I dlatego nie dostajemy żadnych wyników wyszukiwania. Jednak w takim wypadku, powinniśmy dostać wyniki zapytania na następujące zapytanie:

http://localhost:8983/solr/select?q=word:*s*

I tak się dokładnie dzieje, na powyższe zapytanie dostajemy wyniki wyszukiwania, jakich oczekiwaliśmy.

Możliwe rozwiązania

Jeżeli ktoś zapytał by mnie jakie rozwiązanie bym zasugerował, odpowiedziałbym, że w tym momencie po stronie aplikacji usuwałbym polskie znaki z zapytań które mają w sobie wildcardy. Od wersji 1.5 Solr, ReversedWildcardFilterFactory będzie poprawnie obsługiwać znaki spoza podstawowej tablicy ASCII, tak więc nie będzie konieczności korzystania z ASCIIFoldingFilterFactory, a co za tym idzie, problem nie będzie występował

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *