Czekając na 4.0: Solr-2272, czyli Solr i funkcjonlaność Join

W ostatnim czasie moją uwagę przykuła funkcjonalność opisania w zgłoszeniu SOLR-2272, czyli funkcjonalność SQL’owego JOIN zaimplementowanego w Solr. W dzisiejszym wpisie przyjrzymy się bliżej tej funkcjonalności.

Przygotowanie

Pierwszą rzeczą jaką musimy zrobić to pobranie kodu z głównej gałęzi (trunk) repozytorium SVN projektów Lucene/Solr i dodanie nałożenie na ten kod łatki załączonej do zgłoszenia SOLR-2272. Później kilka chwil na zbudowanie Solr i możemy przystępować do testów.

Struktura indeksu

Do celów testowych zdecydowałem się zdefiniować następującą strukturę indeksu:

<fields>
  <field name="id" type="string" indexed="true" stored="true" required="true" />
  <field name="name" type="text" indexed="true" stored="true"/>
  <field name="color" type="string" indexed="true" stored="true"/>
  <field name="parent" type="string" indexed="true" stored="true"/>
</fields>

Sama struktura jest raczej prosta. Pole id odpowiada za przechowywanie unikalnego identyfikatora dokumentu. Pole name odpowiada za nazwę dokumentu, color to kolor produktu, a pole parent to identyfikator rodzica.

Dane testowe

Plik z przykładowymi danymi wygląda następująco:

<add>
 <doc>
  <field name="id">1</field>
  <field name="name">First document</field>
  <field name="color">Red</field>
 </doc>
 <doc>
  <field name="id">2</field>
  <field name="name">Second document</field>
  <field name="color">Yellow</field>
 </doc>
 <doc>
  <field name="id">3</field>
  <field name="name">Third document</field>
  <field name="color">Red</field>
  <field name="parent">1</field>
 </doc>
 <doc>
  <field name="id">4</field>
  <field name="name">Fourth document</field>
  <field name="color">Yellow</field>
  <field name="parent">1</field>
 </doc>
</add>

Przykład zapytania

Do krótkich testów jakie przeprowadziłem wybrałem dość prosty przypadek. W odpowiedzi na zapytanie chciałem dostać dokumenty, które są rodzicami dokumentów posiadających w polu color wartość Yellow. Nic nadzwyczajnego, przynajmniej w rozumieniu SQL. Aby wykonać takie zapytanie w standardowym Solr musielibyśmy wykonać przynajmniej dwa zapytania – pierwsze o dokumenty z odpowiednią wartością w polu, a następnie o dokumenty rodziców. A jak wygląda to w przypadku Solr 4.0 i łatki ze zgłoszenia SOLR-2272 ? Poniżej zapytanie:

http://localhost:8983/solr/select?q={!join from=parent to=id}color:Yellow

I odpowiedź Solr:

<?xml version="1.0" encoding="UTF-8"?>
<response>
<lst name="responseHeader">
  <int name="status">0</int>
  <int name="QTime">1</int>
  <lst name="params">
    <str name="q">{!join from=parent to=id}color:Yellow</str>
  </lst>
</lst>
<result name="response" numFound="1" start="0">
  <doc>
    <str name="color">Red</str>
    <str name="id">1</str>
    <str name="name">First document</str>
  </doc>
</result>
</response>

Jak widać dostaliśmy wyniki takie, jakich się spodziewaliśmy. Jednak jak działa to zapytanie ? Jak widać na załączonym przykładzie oprócz standardowego pobrania dokumentów, które mają w polu jakąś wartość (color:Yellow) dochodzi dość specyficzna konstrukcja {!join from=parent to=id}. Fragment ten mówi Solr, aby pokazać nie dokumenty oryginalne, ale te, które mają wartość w polu id taką samą jak pole parent dokumentów spełniających wcześniejszy warunek.

Weryfikacja

Sprawdźmy, czy to działa. Najpierw pobierzmy dokumenty, które spełniają posiadają w polu color wartość Yellow.W tym celu zadajemy zapytanie:

http://localhost:8983/solr/select?q=color:Yellow

Odpowiedź Solr, była następująca:

<?xml version="1.0" encoding="UTF-8"?>
<response>
<lst name="responseHeader">
  <int name="status">0</int>
  <int name="QTime">2</int>
  <lst name="params">
    <str name="q">color:Yellow</str>
  </lst>
</lst>
<result name="response" numFound="2" start="0">
  <doc>
    <str name="color">Yellow</str>
    <str name="id">2</str>
    <str name="name">Second document</str>
  </doc>
  <doc>
    <str name="color">Yellow</str>
    <str name="id">4</str>
    <str name="name">Fourth document</str>
    <str name="parent">1</str>
  </doc>
</result>
</response>

Mamy zatem jeden dokument, który posiada wartość w polu parent – wartość ta to 1. Dokument o id równym jeden jest następujacy:

<?xml version="1.0" encoding="UTF-8"?>
<response>
<lst name="responseHeader">
  <int name="status">0</int>
  <int name="QTime">4</int>
  <lst name="params">
    <str name="indent">true</str>
    <str name="q">id:1</str>
  </lst>
</lst>
<result name="response" numFound="1" start="0">
  <doc>
    <str name="color">Red</str>
    <str name="id">1</str>
    <str name="name">First document</str>
  </doc>
</result>
</response>

Widać zatem, że zapytanie z JOIN’em zadziałało prawidłowo 😉

Kilka słów na koniec

Warto pamiętać, że w obecnej chwili funkcjonalność jest w fazie rozwojowej i może się zmieniać. Ważne jest jednak to, że w wersji 4.0 Solr będziemy mogli cieszyć się funkcjonalnością podobną do SQL’owego JOIN.

This entry was posted on poniedziałek, Luty 21st, 2011 at 09:21 and is filed under Solr. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

2 komentarze to “Czekając na 4.0: Solr-2272, czyli Solr i funkcjonlaność Join”

  1. dawka902 Says:

    Witam,
    Mam taki problem:
    Mam dwa indeksy
    tags { tagid,Keyword}
    products { productid,description}

    Chciałbym zwrócić sobie listę tych elementów wraz z id atrybutu który jest wyszukiwany w opisie tych dokumentów
    /dev/tags/select/?q={!join+from=Keyword+to=Description+fromIndex=products}*:*
    Puszczam takie zapytanie i zwracam sobie listę tagów, ale nie wiem w jakiś sposób mam sobie dociągnąć listę produktów do tych tagów.

    W SQL nie ma problemu ponieważ jak robię join między dwoma tabelami to mam listę kolumn z obu tabel jak to samo zrobić w solr?

  2. gr0 Says:

    Z tego co wiem na temat join’a w Solr to nie zadziała tak jak w bazie danych i nie zrobi unii z dwóch rdzeni. Za pomocą join’a w Solr możemy sobie tylko ‚przefiltrować’ dane, ale niestety nie połączymy ich, przynajmniej w tym momencie.