Wraz z niedawną premierą Solr 5.1 doczekaliśmy się szeregu nowości. Jedną z nich jest przepisany moduł facetingu umożliwiający konstruowanie zapytań w oparciu o format JSON. W niniejszym wpisie postaram się pokrótce przyjrzeć tej funkcjonlaności i zobaczyć, jak Solr zmienia się jako narzędzie do analizy danych w czasie rzeczywistym.
Dane testowe
Do naszych testów wykorzystamy dane dostarczane wraz z domyślną dystrybucją Solr. Do uruchomienia Solr wykorzystujemy komendę:
bin/solr start -e techproducts
Spowoduje to uruchomienie Solr oraz zaindeksowanie przykładowych danych – wszystko to w kolekcji techproducts.
Przykład pierwszy
Zacznijmy od bardzo prostego przykładu z wykorzystaniem nowego facetingu – spróbujmy pobrać od Solr faceting dotyczący producentów oraz kategorii naszych produktów. Zapytanie, do którego jesteśmy przezwyczajeni wyglądało by następująco:
curl 'localhost:8983/solr/techproducts/select?q=*:*&rows=0&indent=true&facet=true&facet.field=manu_id_s&facet.field=cat'
Zapytanie wykorzystujące nowe API wygląda następująco:
curl http://localhost:8983/solr/techproducts/query -d 'q=*:*&rows=0& json.facet={ categories : { terms : { field: cat } }, producers : { terms : { field: manu_id_s } } }'
Odpowiedź na powyższe zapytanie wygląda następująco:
{ "responseHeader":{ "status":0, "QTime":2, "params":{ "q":"*:*", "json.facet":"{\n categories : {\n terms : {\n field: cat\n } \n },\n manu : {\n terms : {\n field: manu_id_s\n }\n }\n}", "rows":"0"}}, "response":{"numFound":32,"start":0,"docs":[] }, "facets":{ "count":32, "categories":{ "buckets":[{ "val":"electronics", "count":12}, { "val":"currency", "count":4}, { "val":"memory", "count":3}, { "val":"connector", "count":2}, { "val":"graphics card", "count":2}, { "val":"hard drive", "count":2}, { "val":"search", "count":2}, { "val":"software", "count":2}, { "val":"camera", "count":1}, { "val":"copier", "count":1}]}, "manu":{ "buckets":[{ "val":"corsair", "count":3}, { "val":"belkin", "count":2}, { "val":"canon", "count":2}, { "val":"apple", "count":1}, { "val":"asus", "count":1}, { "val":"ati", "count":1}, { "val":"boa", "count":1}, { "val":"dell", "count":1}, { "val":"eu", "count":1}, { "val":"maxtor", "count":1}]}}}
Jak widać samo zapytanie, jak i odpowiedź jest czymś do czego nie jesteśmy przezwyczajeni w pracy z Solr. Zacznijmy więc od zapytania.
Zapytanie
Tym razem zapytanie wysłaliśmy do handlera query, ale nie to jest ważne. Najważniejsze jest to, jak wygląda samo zapytanie. Wszystkie parametry zapytania nie zostały przekazane jako parametry rządania HTTP. Tym razem wszystkie parametry zostały przekazane w ciele rządania w formie podobnej do tego do czego jesteśmy przezwyczajeni. Oprócz tego dodaliśmy nowy parametr – facet.json, gdzie zdefiniowaliśmy nasz faceting.
W Solr 5.1, każdy faceting, jaki chcemy wykonać definiujemy następująco:
NAZWA: { TYP: { PARAMETR: WARTOSC ... PARAMETR: WARTOSC } }
W Solr 5.2, ten format zmieni się delikatnie, ale wrócimy do tego, jak tylko pojawi się Solr 5.2. W naszym przykładzie wykorzystaliśmy typ terms, który funkcjonuje tak samo, jak zachowanie znane nam, gdy korzystaliśmy z facet.field. Inne typy to np. query, czy range. Po możliwe do wykorzystania parametry odsyłamy do oficjalnej dokumentacji Solr.
Wyniki
Jeżeli natomiast spojrzymy na wyniki zwrócone przez Solr widzimy coś co nazywa się buckets. Są to grupy klucz – wartość opisujące nasz faceting – niby coś nowego, ale jednak znajome. Korzystając z nowego API facetingu możemy spotkać się z dwoma rodzajami zwracanych wyników – pojedyńczą wartością oraz właśnie bucketami. Opiszemy to dokładniej w chwili premiery Solr 5.2.
Facting i funkcje
Sprawdźmy jeszcze jeden przypadek – znalezienie średniej ceny produktów oraz 99 percentyla ceny. Solr umożliwia skorzytanie z szeregu funkcji w ramach nowego modułu facetingu, a zapytanie które umożliwi nam realizację naszego celu wygląda następująco:
curl http://localhost:8983/solr/techproducts/query -d 'q=*:*&rows=0& json.facet={ average:"avg(price)", percentile:"percentile(price,99)" }'
Wynik zapytania wygląda następująco:
{ "responseHeader":{ "status":0, "QTime":2, "params":{ "q":"*:*", "json.facet":"{\n average:\"avg(price)\",\n percentile:\"percentile(price,99)\"\n }", "rows":"0"}}, "response":{"numFound":32,"start":0,"docs":[] }, "facets":{ "count":32, "average":164.10218846797943, "percentile":1966.6484985351556}}
Solr zwrócił to co chcieliśmy, a Solr zwrócił pojedyncze wartości dla każdej z funkcji.
Co dalej?
Oczywiście to nie wszystko co Solr oferuje nam w tym momencie oraz co planowane jest w przyszłości. Po pierwsze ilość funkcji zostanie rozszerzona – np. o możliwość pobierania unikalnych wartości. Dodatkowo, w Solr 5.2, dostaniemy możliwość zagnieżdżania facetingu i genrowania wyników zapytań zwracających np. minimalne wartości, dla każdej z grup kategorii zwróconej przez terms faceting.