Hibernate Search Skuteczne wyszukiwanie

background image
background image

Tytuł oryginału: Hibernate Search by Example

Tłumaczenie: Andrzej Bobak

ISBN: 978-83-246-8600-1
Copyright © Packt Publishing 2013.
First published in the English language under the title ‘Hibernate Search by Example’.

Polish edition copyright © 2014 by Helion S.A.
All rights reserved.

All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means,
electronic or mechanical, including photocopying, recording or by any information storage retrieval system,
without permission from the Publisher.

Wszelkie prawa zastrzeżone. Nieautoryzowane rozpowszechnianie całości lub fragmentu niniejszej
publikacji w jakiejkolwiek postaci jest zabronione. Wykonywanie kopii metodą kserograficzną,
fotograficzną, a także kopiowanie książki na nośniku filmowym, magnetycznym lub innym powoduje
naruszenie praw autorskich niniejszej publikacji.

Wszystkie znaki występujące w tekście są zastrzeżonymi znakami firmowymi bądź towarowymi ich
właścicieli.

Autor oraz Wydawnictwo HELION dołożyli wszelkich starań, by zawarte w tej książce informacje były
kompletne i rzetelne. Nie biorą jednak żadnej odpowiedzialności ani za ich wykorzystanie, ani za związane
z tym ewentualne naruszenie praw patentowych lub autorskich. Autor oraz Wydawnictwo HELION nie
ponoszą również żadnej odpowiedzialności za ewentualne szkody wynikłe z wykorzystania informacji
zawartych w książce.

Wydawnictwo HELION
ul. Kościuszki 1c, 44-100 GLIWICE
tel. 32 231 22 19, 32 230 98 63
e-mail: helion@helion.pl
WWW: http://helion.pl (księgarnia internetowa, katalog książek)

Drogi Czytelniku!
Jeżeli chcesz ocenić tę książkę, zajrzyj pod adres
http://helion.pl/user/opinie/hibers
Możesz tam wpisać swoje uwagi, spostrzeżenia, recenzję.

Pliki z przykładami omawianymi w książce można znaleźć pod adresem:
ftp://ftp.helion.pl/przyklady/hibers.zip

Printed in Poland.

Kup książkę

Poleć książkę

Oceń książkę

Księgarnia internetowa

Lubię to! » Nasza społeczność

background image

Spis treĂci

Przedmowa

9

Czym jest Hibernate Search?

10

ZawartoĂÊ ksiÈĝki

11

Co jest potrzebne, by korzystaÊ z tej ksiÈĝki

12

Dla kogo jest ta ksiÈĝka

12

Konwencje

12

Wsparcie klienta

13

Kod ěródïowy do pobrania

13

Errata

13

Rozdziaï 1. Twoja pierwsza aplikacja

15

Tworzenie klasy encji

16

Dostosowywanie encji do Hibernate Search

18

’adowanie danych testowych

19

Tworzenie pierwszego zapytania

21

Wybór narzÚdzia do automatycznego budowania projektu

25

Tworzenie projektu oraz importowanie Hibernate Search

26

Uruchamianie aplikacji

29

Podsumowanie

33

Rozdziaï 2. Mapowanie klas encji

35

Wybieramy API mapera obiektowo-relacyjnego Hibernate

35

Opcje mapowania pól

38

Wielokrotne mapowanie jednego pola

39

Mapowanie pól liczbowych

39

ZaleĝnoĂci pomiÚdzy encjami

40

PowiÈzane encje

40

Wbudowane obiekty

43

CzÚĂciowe indeksowanie

46

Programowe API do mapowania

47

Podsumowanie

49

Kup książkę

Poleć książkę

background image

Spis

treĞci

4

Rozdziaï 3. Wykonywanie zapytañ

51

API do mapowania kontra API do tworzenia zapytañ

51

Tworzenie zapytañ w JPA

52

Konfiguracja projektu dla Hibernate Search i JPA

54

Hibernate Search DSL

54

Zapytania na podstawie sïów kluczowych

55

Wyszukiwanie na podstawie dokïadnej frazy

58

Zapytania na podstawie zakresu

59

Boolowskie (ïÈczone) zapytania

60

Sortowanie

62

Stronicowanie

63

Podsumowanie

64

Rozdziaï 4. Zaawansowane mapowanie

65

Transformery

65

Konwersje jeden-do-jednego

66

Zïoĝone mapowania z uĝyciem FieldBridge

70

Analiza

73

Filtrowanie znaków

73

Tokenizowanie

74

Filtrowanie tokenów

74

Definiowanie i wybór analizatorów

75

ZwiÚkszanie waĝnoĂci wyników wyszukiwania

78

Statyczne zwiÚkszanie waĝnoĂci podczas indeksowania

78

Dynamiczne zwiÚkszanie waĝnoĂci podczas indeksowania

79

Warunkowe indeksowanie

80

Podsumowanie

82

Rozdziaï 5. Zaawansowane zapytania

83

Filtrowanie

83

Tworzenie fabryki filtrów

84

Tworzenie definicji filtru

86

Uĝywanie filtru w zapytaniu

87

Projekcje

88

Tworzenie zapytañ korzystajÈcych z projekcji

88

Konwertowanie wyników projekcji na obiekty

89

UdostÚpnianie pól Lucene do projekcji

89

Wyszukiwanie fasetowe

90

Dyskretne fasety

91

Fasety z zakresami

93

ZwiÚkszanie waĝnoĂci na czas wyszukiwania

95

Nakïadanie limitów czasowych na zapytanie

96

Podsumowanie

97

Kup książkę

Poleć książkę

background image

Spis treĞci

5

Rozdziaï 6. Konfiguracja systemu i zarzÈdzanie indeksami

99

Automatyczne i rÚczne indeksowanie

99

Indywidualne aktualizacje

100

Grupowe aktualizacje

101

Defragmentowanie indeksu

102

RÚczna optymalizacja

103

Automatyczna optymalizacja

104

Wybór menedĝera indeksowania

105

Konfigurowanie procesów roboczych

106

Tryb wykonywania

107

Pula wÈtków

107

Bufor kolejki

108

Wybór i konfiguracja dostawcy katalogów

108

Dostawca katalogów opierajÈcy siÚ na systemie plików

108

Dostawca katalogów opierajÈcy siÚ na pamiÚci RAM

110

Uĝywanie narzÚdzia Luke

111

Podsumowanie

114

Rozdziaï 7. Zaawansowane strategie poprawy wydajnoĂci

117

Ogólne porady

117

Uruchamianie aplikacji w klastrze

118

Proste klastry

118

Klastry nadrzÚdny-podrzÚdny

119

Horyzontalne partycjonowanie indeksów Lucene

125

Podsumowanie

127

Skorowidz

129

Kup książkę

Poleć książkę

background image

Spis

treĞci

6

Kup książkę

Poleć książkę

background image

3

Wykonywanie zapytañ

W poprzednim rozdziale stworzyïeĂ kilka typów trwaïych obiektów i zmapowaïeĂ je do in-
deksów Lucene na parÚ róĝnych sposobów. Do tej pory uĝywaïeĂ jednego rodzaju wyszuki-
wania na podstawie sïowa kluczowego we wszystkich wersjach przykïadowej aplikacji.

W tym rozdziale poznasz inne typy wyszukiwañ dostÚpne w DSL Hibernate Search. Dowiesz
siÚ równieĝ, na czym polegajÈ niektóre istotne operacje, takie jak sortowanie i stronicowanie
wyników.

API do mapowania

kontra API do tworzenia zapytañ

Do tej pory omawialiĂmy alternatywne API do mapowania klas na tabele bazy danych za po-
mocÈ mapera obiektowo-relacyjnego Hibernate. Moĝesz mapowaÊ swoje klasy zarówno przy
uĝyciu plików XML, jak i adnotacji Hibernate lub JPA. Hibernate Search bÚdzie poprawnie
obsïugiwaÊ kaĝde ze wspomnianych podejĂÊ, o ile uĂwiadomisz sobie drobne róĝnice miÚ-
dzy nimi.

Gdy chcesz sprecyzowaÊ, z którego API korzysta aplikacja Hibernate, musisz ustaliÊ dwie
kwestie. Po pierwsze, istnieje kilka sposobów mapowania klas na tabele w bazie danych. Po
drugie, dostÚpne sÈ róĝne metody odpytywania bazy danych w czasie pracy programu. Maper
obiektowo-relacyjny Hibernate ma tradycyjne API opierajÈce siÚ na klasach

SessionFactory

i

Session

oraz API zgodne ze standardami JPA, bazujÈce na klasach

EntityManagerFactory

i

EntityManager

.

Kup książkę

Poleć książkę

background image

Hibernate Search. Skuteczne wyszukiwanie

52

MyĂlÚ, ĝe zauwaĝyïeĂ, iĝ w naszym przykïadowym kodzie klasy byïy mapowane na tabele ba-
zodanowe za pomocÈ adnotacji JPA, natomiast zapytania wykonywano z uĝyciem obiektu klasy

Session

, pochodzÈcego z tradycyjnego Hibernate. Na pierwszy rzut oka pewnie wyda Ci siÚ

to nieco mylÈce, jednak API do mapowania oraz API do tworzenia zapytañ mogÈ byÊ stoso-
wane zamiennie.

Pewnie zastanawiasz siÚ, którego z podejĂÊ powinieneĂ uĝyÊ w projektach opierajÈcych siÚ na
Hibernate Search? Z jednej strony trzymanie siÚ standardów ma pewne zalety. Gdy nabie-
rzesz doĂwiadczenia w uĝywaniu JPA, bÚdziesz w stanie wykorzystywaÊ zdobyte umiejÚtnoĂci
w projektach posïugujÈcych siÚ róĝnymi implementacjami JPA.

Z drugiej strony API mapera obiektowo-relacyjnego Hibernate jest bardziej rozbudowane niĝ
standard JPA. Ponadto Hibernate Search stanowi rozwiniÚcie projektu ORM Hibernate. Nie
ma równieĝ gwarancji, ĝe zmiana implementacji JPA bÚdzie wykonalna bez wiÚkszych inge-
rencji w napisane juĝ zapytania.

Uĝywanie standardu JPA jest, ogólnie rzecz biorÈc, wskazane. Jednak maper obiektowo-relacyjny Hibernate
okazuje siÚ niezbÚdny do dziaïania Hibernate Search. W zwiÈzku z tym nie ma sensu unikaÊ za wszelkÈ
cenÚ rozwiÈzañ z klasycznego Hibernate. WiÚkszoĂÊ kodu ěródïowego w tej ksiÈĝce uĝywa adnotacji JPA do
mapowania encji oraz klasy Session, pochodzÈcej z tradycyjnego wrappera, do wykonywania zapytañ.

Tworzenie zapytañ w JPA

Pomimo ĝe skupisz siÚ na wykonywaniu zapytañ z uĝyciem tradycyjnego API, dostÚpny do
ĂciÈgniÚcia kod ěródïowy znajduje siÚ z katalogu rozdzial3-entitymanager. Zawiera on alter-
natywnÈ wersjÚ przykïadowej aplikacji, w której zaprezentowano uĝycie JPA zarówno do ma-
powania, jak i tworzenia zapytañ.

Gïówna zmiana jest widoczna w servlecie implementujÈcym kontroler odpowiedzialny za wy-
szukiwanie. Zamiast uĝyÊ znanego z Hibernate obiektu typu

SessionFactory

w celu utworzenia

obiektu klasy

Session

, skorzystasz z pochodzÈcego z JPA obiektu klasy

EntityManagerFactory

,

aby utworzyÊ obiekt typu

EntytyManager

:

...
// Identyfikator "com.packtpub.hibernatesearch.jpa" jest zadeklarowany
// w "META-INF/persistence.xml."
EntityManagerFactory entityManagerFactory =
Persistence.createEntityManagerFactory(
"com.packtpub.hibernatesearch.jpa");
EntityManager entityManager =
entityManagerFactory.createEntityManager();
...

Kup książkę

Poleć książkę

background image

Rozdziaá 3. • Wykonywanie zapytaĔ

53

MiaïeĂ juĝ do czynienia z fragmentami kodu prezentujÈcymi zapytania w tradycyjnym API.
W dotychczasowych przykïadach pochodzÈce z mapera obiektowo-relacyjnego Hibernate
obiekty typu

Session

byïy opakowane obiektami typu

FullTextSession

wywodzÈcymi siÚ

z Hibernate Search. Te z kolei zwracaïy obiekty typu

FullTextQuery

, które implementowaïy

interfejs

org.hibernate.Query

:

...
FullTextSession fullTextSession = Search.getFullTextSession(session);
...
org.hibernate.search.FullTextQuery hibernateQuery =
fullTextSession.createFullTextQuery(luceneQuery, App.class);
...

Zauwaĝ, ĝe obiekty typu

FullTextQuery

, implementujÈce interfejs

javax.persistence.Query

,

tworzÈ obiekty typu

FullTextEntityManager

, natomiast pochodzÈce z JPA obiekty

EntityManager

sÈ w nie opakowane:

...
FullTextEntityManager fullTextEntityManager =
org.hibernate.search.jpa.Search.getFullTextEntityManager(
entityManager);
...
org.hibernate.search.jpa.FullTextQuery jpaQuery =
fullTextEntityManager.createFullTextQuery(luceneQuery, App.
class);
...

PochodzÈca z tradycyjnego API Hibernate klasa

FullTextQuery

jest bardzo podobna do jej

odpowiednika wywodzÈcego siÚ z JPA. Obie zapewniajÈ dostÚp zarówno do poznanych juĝ
funkcjonalnoĂci Hibernate Search, jak i tych, które zostanÈ przedstawione w dalszych czÚ-
Ăciach ksiÈĝki. W zasadzie jedynÈ istotnÈ róĝnicÈ jest to, ĝe pochodzÈ z róĝnych pakietów.

Kaĝdy obiekt typu FullTextQuery moĝe byÊ rzutowany z powrotem na typ zapytania, z którego zostaï
utworzony. Taka operacja wymaga bezpoĂredniego dostÚpu do metod Hibernate Search, w zwiÈzku z tym
naleĝy jÈ wykonywaÊ po skoñczeniu pracy z obiektem.
Jeĝeli mimo wszystko potrzebujesz dostÚpu do niestandardowych metod po rzutowaniu na zapytanie JPA,
moĝesz uĝyÊ metody unwrap(), która pozwala na dostÚp do implementacji FullTextQuery.

Kup książkę

Poleć książkę

background image

Hibernate Search. Skuteczne wyszukiwanie

54

Konfiguracja projektu

dla Hibernate Search i JPA

Gdy nasz mavenowy projekt zawiera zaleĝnoĂÊ

hibernate-search

, automatycznie w tle doïÈ-

czonych zostaje okoïo czterdziestu zaleĝnoĂci. Niestety, ĝadna z nich nie zapewnia tworzenia

zapytañ JPA. Aby mieÊ dostÚp do tej funkcjonalnoĂci, musisz samodzielnie dodaÊ zaleĝnoĂÊ

hibernate-entitymanager

.

Jej wersja powinna byÊ zgoda z wersjÈ dodanej wczeĂniej zaleĝnoĂci

hibernate-core

, natomiast

niewykluczone, ĝe nie bÚdzie zgodna z wersjÈ

hibernate-search

.

Jeĝeli Twoje Ărodowisko programistyczne nie dysponuje funkcjonalnoĂciÈ wizualizowania hie-
rarchii zaleĝnoĂci, zawsze moĝesz uĝyÊ komendy Mavena:

mvn dependency:tree

Jak widaÊ na powyĝszym rysunku, Hibernate Search w wersji 4.2.0 Final uĝywa mapera

obiektowo-relacyjnego Hibernate w wersji 4.1.9 Final. W zwiÈzku z tym zaleĝnoĂÊ

hibernate-

entitymanager

równieĝ powinna byÊ dodana w wersji 4.1.9 Final:

...

<dependency>

<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.1.9.Final</version>

</dependency>
...

Hibernate Search DSL

W rozdziale 1. — „Twoja pierwsza aplikacja” — zapoznaïeĂ siÚ z Hibernate Search DSL, naj-
wygodniejszym narzÚdziem do pisania zapytañ. Za pomocÈ DSL ïÈczysz wywoïania metod
w ïañcuch przypominajÈcy skïadniÈ specjalistyczny jÚzyk programowania. Jeĝeli pisaïeĂ juĝ
zapytania z uĝyciem kryteriów w maperze obiektowo-relacyjnym Hibernate, podejĂcie z za-
stosowaniem omawianego narzÚdzia wyda Ci siÚ znajome.

Kup książkę

Poleć książkę

background image

Rozdziaá 3. • Wykonywanie zapytaĔ

55

Niezaleĝnie od tego, czy uĝywasz tradycyjnego obiektu

FullTextSession

, czy znanego z JPA

obiektu

FullTextEntityManager

, kaĝdy z nich przekazuje do Lucene zapytanie utworzone za

pomocÈ klasy

QueryBuilder

. Jest ona poczÈtkowym elementem Hibernate Search DSL, udo-

stÚpniajÈcym kilka typów zapytañ Lucene.

Zapytania na podstawie sïów kluczowych

Najprostszym rodzajem zapytania, z którym, nawiasem mówiÈc, zdÈĝyïeĂ siÚ juĝ zetknÈÊ, jest
to utworzone na podstawie sïów kluczowych. Jak sama nazwa wskazuje, wyszukuje ono obiekty

zawierajÈce wskazane sïowa kluczowe.

Tworzenie zapytania rozpoczyna siÚ od uzyskania obiektu typu

QueryBuilder

, skonfigurowa-

nego dla zadeklarowanej klasy encji:

...
QueryBuilder queryBuilder =

fullTextSession.getSearchFactory().buildQueryBuilder()
.forEntity(App.class ).get();
...

Kolejne kroki zostaïy przedstawione na poniĝszym diagramie. Szare przerywane linie przed-

stawiajÈ opcjonalne kroki:

Kod ěródïowy Javy prezentujÈcy zapytanie na podstawie sïów kluczowych z uĝyciem DSL

wyglÈda mniej wiÚcej tak:

...

org.apache.lucene.search.Query luceneQuery =
queryBuilder

.keyword()
.onFields
("name", "description", "supportedDevices.name",

"customerReviews.comments")

.matching(searchString)

.createQuery();

...

Kup książkę

Poleć książkę

background image

Hibernate Search. Skuteczne wyszukiwanie

56

Parametr przekazywany do metody

onField

to nazwa indeksowanego pola encji. Jeĝeli pole nie

jest skïadowÈ indeksu Lucene, zapytanie bÚdzie bïÚdne. Pola powiÈzanych encji lub wbudo-
wanych obiektów mogÈ byÊ równieĝ przeszukiwane. W tym celu uĝyj formatu

[nazwa pola

zïoĝonego].[nazwa pola w obiekcie zïoĝonym]

, np.

supportedDevices.name

.

Moĝesz dodatkowo posïuĝyÊ siÚ metodÈ

andField

, by uwzglÚdniÊ kolejne pola w wyszukiwaniu.

Jej parametrem jest, podobnie jak w przypadku

onField

, indeksowane pole encji. Ewentualnie

moĝesz uĝyÊ metody

onFields

, by jednoczeĂnie zadeklarowaÊ kilka pól, tak jak w przedsta-

wionym powyĝej przykïadzie.

Metoda porównujÈca pobiera sïowa kluczowe, na podstawie których ma siÚ odbyÊ wyszuki-
wanie. Zazwyczaj przekazywany zostaje ciÈg znaków, jednak technicznie jest moĝliwe prze-
kazanie dowolnego obiektu, w razie gdyby wymagane byïo konwertowanie wartoĂci pola
(przetwarzaniem pól zajmiemy siÚ szerzej w nastÚpnym rozdziale). ZakïadajÈc, ĝe przesyïasz
sïowo lub grupÚ sïów oddzielonych spacjami, Hibernate Search rozbije listÚ na pojedyncze
elementy i wykona wyszukiwanie na podstawie kaĝdego z nich osobno.

Metoda

createQuery

koñczy wyraĝenie w DSL i zwraca obiekt zapytania Lucene, który nastÚp-

nie moĝe zostaÊ wykorzystany przez obiekt typu

FullTextSession

lub

FullTextEntityManager

w celu utworzenia obiektu typu

FullTextQuery

uĝywanego przez Hibernate Search.

...
FullTextQuery hibernateQuery =
fullTextSession.createFullTextQuery(luceneQuery, App.class);
...

Wyszukiwanie rozmyte

Gdy uĝywasz mechanizmu wyszukiwania, zakïadasz, ĝe bÚdzie na tyle „sprytny”, by automa-
tycznie poprawiÊ literówki, gdy sïowo wprowadzone przez Ciebie jako parametr wyszukiwania
jest prawie poprawne. Jeden ze sposobów uzyskania takiego zachowania w Hibernate Search
to sprawienie, by zapytania na podstawie sïów kluczowych uwzglÚdniaïy czÚĂciowe dopaso-
wanie sïów kluczowych.

W przypadku wyszukiwania rozmytego wartoĂÊ pola jest zgodna ze sïowem kluczowym, nawet
jeĂli róĝni siÚ o jeden lub wiÚcej znaków. Zapytanie ma zdefiniowany próg zgodnoĂci sïowa
kluczowego z porównywanÈ wartoĂciÈ. Próg jest liczbÈ rzeczywistÈ w skali od

0

do

1

, gdzie

0

oznacza, ĝe kaĝdy element pasuje do sïowa kluczowego, a

1

sygnalizuje, ĝe wyïÈcznie iden-

tyczny element ma byÊ uznany za pasujÈcy. Stopieñ rozmycia zapytania okreĂlasz wartoĂciÈ
progu. Im bliĝej zera, tym mniej dokïadne musi byÊ dopasowanie.

Budowanie zapytania wyglÈda identycznie jak budowanie zapytania na podstawie sïów klu-
czowych. JedynÈ róĝnicÈ jest moĝliwoĂÊ zadeklarowania, ĝe zapytanie ma byÊ rozmyte, a takĝe
zdefiniowania opcjonalnego progu rozmycia. Diagram przedstawiony poniĝej przedstawia ko-
lejne kroki budowania zapytania:

Kup książkę

Poleć książkę

background image

Rozdziaá 3. • Wykonywanie zapytaĔ

57

Metoda

fuzzy

oznacza zapytanie jako rozmyte, z domyĂlnym progiem o wartoĂci

0,5

. Opcjo-

nalnie za pomocÈ metody

withThreshold

moĝesz okreĂliÊ inny poziom rozmycia. NastÚpnie

zapytanie jest budowane w sposób przedstawiony juĝ podczas omawiania wyszukiwania z uĝy-
ciem sïów kluczowych. Przykïady do tego rozdziaïu majÈ ustawiony próg rozmycia na wartoĂÊ

0,7

. DziÚki temu unikniesz niewïaĂciwych dopasowañ, a jednoczeĂnie umoĝliwisz wyszukanie

na podstawie sïowa, w którym popeïniono literówkÚ, np. bïÚdnie wpisane sïowo kluczowe „rodio”
zostanie dopasowane do sïowa „radio”.

...
luceneQuery = queryBuilder
.keyword()
.fuzzy()
.withThreshold
(0.7f)
.onFields("name", "description", "supportedDevices.name",
"customerReviews.comments")
.matching(searchString)
.createQuery();
...

Dodatkowo za pomocÈ metody

withPrefixLength

moĝesz zadeklarowaÊ, ile poczÈtkowych liter

w sïowach nie powinno zostaÊ rozmyte.

Wyszukiwanie z wieloznacznikami

Drugi z wariantów wyszukiwania z uĝyciem sïów kluczowych nie wymaga stosowania za-
awansowanych algorytmów matematycznych. Jeĝeli kiedykolwiek posïugiwaïeĂ siÚ wzorcem

*.java

, by wyĂwietliÊ wszystkie pliki ěródïowe Javy w katalogu, to podejĂcie wyda Ci siÚ dosyÊ

znajome.

Kup książkę

Poleć książkę

background image

Hibernate Search. Skuteczne wyszukiwanie

58

Wywoïanie metody

wildcard

na obiekcie typu

QueryBuilder

spowoduje, ĝe sïowa kluczowe

zawierajÈce znaki

?

oraz

*

bÚdÈ traktowane niestandardowo. Znak

?

aplikacja zinterpretuje

jako substytut jednego dowolnego znaku, np. sïowo kluczowe

201?

zostanie dopasowane do

wartoĂci

201a

,

2010

,

2011

itp.;

*

stanie siÚ substytutem dowolnego, równieĝ pustego, ciÈgu

znaków, np. sïowo kluczowe

dom*

bÚdzie dopasowane do wartoĂci

domy

,

domek

,

dom

itp.

Budowa zapytania wyglÈda identycznie jak budowa zapytania z uĝyciem sïów kluczowych.

JedynÈ róĝnicÈ jest wywoïanie bezparametrowej metody

wildcard

na obiekcie typu

QueryBuilder

na poczÈtku budowy zapytania.

Wyszukiwanie na podstawie dokïadnej frazy

WpisujÈc sïowa kluczowe do wyszukiwarki, spodziewasz siÚ, ĝe wyniki wyszukiwania bÚdÈ
zawieraïy jedno lub wiÚcej z nich. Niekoniecznie wszystkie sïowa kluczowe muszÈ byÊ obec-

ne w kaĝdym z rezultatów. Ich kolejnoĂÊ równieĝ nie ma znaczenia.

PrzyjÚïo siÚ, ĝe jeĝeli wprowadzisz sïowa kluczowe w cudzysïowie, spodziewasz siÚ, iĝ wyniki

wyszukiwania bÚdÈ zawieraÊ dokïadnÈ frazÚ, którÈ wpisaïeĂ. DSL Hibernate Search udostÚp-
nia wyszukiwanie na podstawie frazy.

Kup książkę

Poleć książkę

background image

Rozdziaá 3. • Wykonywanie zapytaĔ

59

Metody

onField

oraz

andField

dziaïajÈ tak jak zapytania na podstawie sïów kluczowych. Z kolei

sentence

róĝni siÚ od

matching

tym, ĝe jej parametrem musi byÊ zmienna typu

String

.

Zapytania na podstawie dokïadnej frazy mogÈ byÊ w ograniczonym stopniu rozmyte. By uzy-

skaÊ ten efekt, wywoïaj na obiekcie typu

QueryBuilder

metodÚ

withSlop

z liczbÈ caïkowitÈ jako

parametrem okreĂlajÈcym, ile dodatkowych sïów moĝe siÚ znaleěÊ w obrÚbie frazy uznawanej

za poprawny wynik.

Jeĝeli uĝytkownik wprowadzi sïowa kluczowe w cudzysïowie, w naszej aplikacji zostanie wy-
woïany fragment kodu:

...

luceneQuery = queryBuilder
.phrase()

.onField("name")
.andField("description")

.andField("supportedDevices.name")

.andField("customerReviews.comments")

.sentence(unquotedSearchString)
.createQuery();

...

Zapytania na podstawie zakresu

Zapytania na podstawie fraz lub sïów kluczowych polegajÈ na porównywaniu pól z konkretnym
wyraĝeniem. Zapytanie oparte na zakresie jest nieco inne. Sprawdza, czy wartoĂÊ pola speïnia

konkretny warunek, np. czy jest wiÚksza lub mniejsza od wskazanej wartoĂci lub czy mieĂci siÚ

we wskazanym zakresie.

Kup książkę

Poleć książkę

background image

Hibernate Search. Skuteczne wyszukiwanie

60

Zakresy zazwyczaj tworzy siÚ na podstawie wartoĂci liczbowych lub dat. Niemniej jednak
moĝesz to równieĝ zrobiÊ, opierajÈc siÚ na wartoĂci typu

String

. W tym przypadku porównanie

bÚdzie siÚ odbywaÊ wg kolejnoĂci alfabetycznej.

Metoda

above

sprawdza, czy wartoĂÊ pola jest wyĝsza niĝ wartoĂÊ przekazana do metody jako

parametr. Analogicznie

below

kontroluje, czy wartoĂÊ pola jest niĝsza. Natomiast jeĝeli chcesz

sprawdziÊ, czy wartoĂÊ pola mieĂci siÚ w konkretnym zakresie, zastosuj parÚ

from

oraz

to

(pamiÚtaj, ĝe muszÈ byÊ uĝyte razem).

Na kaĝdej z powyĝszych metod moĝna wywoïaÊ bezparametrowÈ metodÚ

excludeLimit

. Jej

zadaniem jest wskazanie, ĝe dany warunek ma byÊ relacjÈ nieostrÈ. Przykïadowo ïañcuch

from(5).to(10).excludeLimit()

oznacza zakres

5 <= x < 10

. Metoda

excludeLimit

zostaïa

wywoïana na

to

. Mogïa byÊ jednak wywoïana na

from

lub obu metodach jednoczeĂnie.

ZaïoĝyliĂmy, ĝe w naszym Bazarze Aplikacji pole

CustomerReview.stars

nie bÚdzie indekso-

wane. GdybyĂ jednak oznaczyï je adnotacjÈ

@Field

, w nastÚpujÈcy sposób mógïbyĂ wyszukaÊ

aplikacje oznaczone czteroma lub piÚcioma gwiazdkami:

...
luceneQuery = queryBuilder
.range()
.onField("customerReviews.stars")
.above(3).excludeLimit()
.createQuery();
...

Boolowskie (ïÈczone) zapytania

Zaïóĝmy, ĝe musisz utworzyÊ zïoĝone zapytanie, którego wyniki powinny speïniaÊ kilka wa-
runków umieszczonych w podzapytaniach. Hibernate Search umoĝliwia ïÈczenie zapytañ za
pomocÈ boolowskiej logiki:

Kup książkę

Poleć książkę

background image

Rozdziaá 3. • Wykonywanie zapytaĔ

61

Metoda

bool

wskazuje, ĝe masz do czynienia z zapytaniem kombinacyjnym. NastÚpnie na-

leĝy uĝyÊ co najmniej jednej metody

must

lub

should

. Parametrem kaĝdej z nich jest zapy-

tanie Lucene.

Jeĝeli uĝyjesz

must

, wynikiem wyszukiwania bÚdzie obiekt speïniajÈcy warunki podane w za-

gnieĝdĝonym zapytaniu. Zastosowanie jednoczeĂnie kilku takich metod odpowiada logicz-
nemu wyraĝeniu

AND

. Wynikiem wyszukiwania bÚdzie obiekt speïniajÈcy wszystkie warunki

wszystkich zapytañ.

Opcjonalna metoda

not

sïuĝy logicznemu zanegowaniu

must

. Oznacza to, ĝe obiekt jest wyni-

kiem wyszukiwania, jeĝeli nie speïnia warunków zagnieĝdĝonego zanegowanego zapytania.

Metoda

should

przypomina logicznÈ operacjÚ

OR

. Jeĝeli ïÈczone zapytanie skïada siÚ wyïÈcz-

nie z metod

should

, obiekt bÚdÈcy wynikiem zapytania musi speïniaÊ co najmniej jedno z za-

wartych w nich podzapytañ.

Moĝesz ïÈczyÊ metody must oraz should. W takim przypadku podzapytania w should stajÈ siÚ opcjo-
nalne. Jeĝeli podzapytania w metodach must sÈ speïnione, obiekt zostaje zwrócony jako poprawny wy-
nik zapytania. Nie ma znaczenia, czy speïnia warunki w podzapytaniach zawartych w should. Jeĝeli
warunki dowolnego podzapytania w must nie sÈ speïnione, obiekt jest traktowany jako niespeïniajÈcy warun-
ków caïego zapytania. JeĂli uĝywasz jednoczeĂnie obu typów metod, wyniki podzapytañ w should sïuĝÈ
wyïÈcznie do ustalenia istotnoĂci rezultatu wyszukiwania.

Poniĝszy przykïad ïÈczy zapytanie na podstawie sïów kluczowych z zapytaniem opartym na
zakresie. Poszukiwane sÈ aplikacje zawierajÈce sïowo kluczowe „xPhone” oraz majÈce piÚcio-
gwiazdkowe opinie uĝytkowników:

...
luceneQuery = queryBuilder
.bool()
.must(
queryBuilder.keyword().onField("supportedDevices.name")
.matching("xphone").createQuery()
)
.must(
queryBuilder.range().onField("customerReviews.stars")
.above(5).createQuery()
)
.createQuery();
...

Kup książkę

Poleć książkę

background image

Hibernate Search. Skuteczne wyszukiwanie

62

Sortowanie

DomyĂlnie wyniki wyszukiwania zostajÈ zwrócone w kolejnoĂci odzwierciedlajÈcej ich traf-
noĂÊ. Innymi sïowy, sÈ posortowane wg stopnia dopasowania do zapytania. To zagadnienie zo-
stanie omówione w nastÚpnych dwóch rozdziaïach. Nauczysz siÚ równieĝ modyfikowaÊ wyli-
czenia waĝnoĂci.

Masz jednak moĝliwoĂÊ ustalenia kryteriów sortowania. Zazwyczaj chcesz, by wyniki wyszu-
kiwania zostaïy uporzÈdkowane alfabetycznie, wedïug daty lub wartoĂci liczbowych. Od tej
pory we wszystkich wersjach naszego Bazaru Aplikacji uĝytkownicy bÚdÈ mogli sortowaÊ re-
zultaty po nazwie aplikacji.

Musisz podjÈÊ pewne kroki, aby umoĝliwiÊ porzÈdkowanie wyników na podstawie pola ma-
powanego w indeksie Lucene. Zazwyczaj gdy pole jest indeksowane, domyĂlny analizator
rozbija ciÈg znaków na pojedyncze sïowa. Jeĝeli pole

name

encji typu

App

ma wartoĂÊ „Sfru-

strowane Flamingi”, w indeksie Lucene pojawiajÈ siÚ wpisy dla „sfrustrowane” oraz „flamingi”.
DziÚki temu masz moĝliwoĂÊ budowania bardziej wydajnych zapytañ. Co jednak, jeĂli chcesz
sortowaÊ wyniki na podstawie oryginalnej, nierozbitej wartoĂci?

Prosty sposób to dwukrotne mapowanie pola. Jak przekonaïeĂ siÚ podczas lektury rozdziaïu 2.
— „Mapowanie klas encji” — w Hibernate Search jest dostÚpna adnotacja

@Fields

. Moĝesz

uĝyÊ jej do opakowania kilku adnotacji

@Field

, kaĝdej z innymi ustawieniami analizatora.

Poniĝszy fragment kodu prezentuje dwa mapowania jednego pola. Pierwsze jest zadeklaro-
wane z domyĂlnymi ustawieniami analizatora. Drugie ma nadany parametr

analyze

o wartoĂci

Analyze.NO

, zapobiegajÈcy rozbijaniu wartoĂci pola, a takĝe nadanÈ unikalnÈ nazwÚ pola w in-

deksie Lucene:

...
@Column
@Fields({
@Field,
@Field(name="sorting_name", analyze=Analyze.NO)
})
private String name;
...

Nowe pole moĝe zostaÊ uĝyte do zbudowania obiektu Lucene typu

SortField

i dodania go do

obiektu Hibernate Search typu

FullTextQuery

:

import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
...
Sort sort = new Sort(
new SortField("sorting_name", SortField.STRING));
hibernateQuery.setSort(sort); // obiekt typu FullTextQuery

Kup książkę

Poleć książkę

background image

Rozdziaá 3. • Wykonywanie zapytaĔ

63

Gdy obiekt

hibernateQuery

zwróci wyniki wyszukiwania, bÚdÈ one posortowane rosnÈco po

nazwie aplikacji.

Aby porzÈdkowaÊ w kolejnoĂci malejÈcej, wywoïaj trójparametrowy konstruktor klasy

SortField

.

Trzeci z parametrów, typu

Boolean

, precyzuje, czy sortowanie ma siÚ odbyÊ rosnÈco (wartoĂÊ

Boolean.FALSE

), czy malejÈco (wartoĂÊ

Boolean.TRUE

).

Stronicowanie

Zazwyczaj gdy wynik zapytania zawiera bardzo duĝo elementów, nie jest wskazane przedsta-
wianie ich wszystkich jednoczeĂnie. Popularne rozwiÈzanie w takiej sytuacji stanowi stroni-
cowanie, czyli prezentowanie wyników porcjami.

Metody dostÚpne w obiekcie Hibernate Search typu

FullTextQuery

sprawiajÈ, ĝe jest to bardzo

proste:

...
hibernateQuery.setFirstResult(10);
hibernateQuery.setMaxResults(5);
List<App> apps = hibernateQuery.list();
...

Metoda

setMaxResults

wskazuje maksymalnÈ liczbÚ wyników zwracanych na jednej stronie.

W powyĝszym przykïadzie zadeklarowano, ĝe wynik bÚdzie zawieraï nie wiÚcej niĝ piÚÊ ele-
mentów, niezaleĝnie od liczby obiektów pasujÈcych do zapytania.

Stronicowanie nie miaïoby sensu, gdybyĂ za kaĝdym razem otrzymywaï pierwsze piÚÊ wyni-
ków. PowinieneĂ móc pobieraÊ kolejne strony z wynikami. UĝywajÈc metody

setFirstResult

,

wskazujesz poczÈtkowe miejsce.

Przedstawiony powyĝej fragment kodu wskazuje, ĝe interesuje CiÚ piÚÊ wyników, poczÈwszy
od jedenastego (wartoĂÊ parametru wynosi

10

, jednak indeksowanie odbywa siÚ od zera). Aby

w kolejnym kroku przetworzyÊ kolejne piÚÊ wyników, wystarczy, ĝe w powyĝszym przykïadzie
zamienisz pierwszÈ liniÚ na

hibernateQuery.setFirstResult(15)

.

OstatniÈ niezbÚdnÈ informacjÈ jest ïÈczna liczba wyników pasujÈcych do zapytania. Potrze-
bujesz jej, aby wyliczyÊ, ile stron z wynikami bÚdziesz prezentowaÊ:

...
intresultSize = hibernateQuery.getResultSize();
...

Kup książkę

Poleć książkę

background image

Hibernate Search. Skuteczne wyszukiwanie

64

Metoda

getResultSize

jest bardziej interesujÈca, niĝ mogïoby siÚ wydawaÊ na pierwszy rzut oka.

Do okreĂlenia liczby pasujÈcych rezultatów uĝywa indeksów Lucene. W odróĝnieniu od za-
pytania Lucene tradycyjne zapytanie bazodanowe, wyszukujÈce wszystkie rezultaty, pochïo-
nÚïoby duĝo zasobów.

W tym rozdziale nasza aplikacja zostaïa wzbogacona o mechanizm stronicowania. Kaĝda strona wyników
prezentuje piÚÊ rezultatów wyszukiwania. Przyjrzyj siÚ klasie SearchServlet oraz plikowi

search.jsp

,

aby zobaczyÊ, jak wykorzystano w nich informacjÚ o ïÈcznej liczbie wyników. Zbadaj równieĝ, w jaki spo-
sób zostaïy w nich uĝyte dane o ïÈcznej liczbie obiektów speïniajÈcych warunki wyszukiwania oraz punkt
poczÈtkowy wyników w celu zbudowania odnoĂników „Poprzednie” oraz „NastÚpne”.

Nasza aplikacja wyglÈda obecnie tak:

Podsumowanie

W tym rozdziale przedstawiono najpopularniejsze przypadki uĝycia zapytañ Hibernate Search.
Moĝesz juĝ korzystaÊ z Hibernate Search, niezaleĝnie od tego, czy Twoja aplikacja uĝywa JPA.
PoznaïeĂ gïówne typy zapytañ tworzonych za pomocÈ Hibernate Search DSL. PrzyjrzaïeĂ siÚ
równieĝ diagramom prezentujÈcym sposób budowania poszczególnych zapytañ.

Umiesz juĝ sortowaÊ rosnÈco lub malejÈco wyniki zapytania na podstawie dowolnego indek-
sowanego pola. Potrafisz dzieliÊ je na strony w celu usprawnienia wydajnoĂci procesu wyszu-
kiwania oraz przejrzystoĂci prezentacji rezultatów. FunkcjonalnoĂÊ wyszukiwania w Bazarze
Aplikacji jest teraz zbliĝona do wielu produkcyjnych aplikacji uĝywajÈcych Hibernate Search.

W kolejnym rozdziale poznasz zaawansowane techniki mapowania, takie jak niestandardowe
typy danych oraz kontrolowanie szczegóïów procesu indeksowania w Lucene.

Kup książkę

Poleć książkę

background image

Skorowidz

A

adnotacja

@Analyzer, 76
@AnalyzerDiscriminator, 77
@Column, 18
@ContainedIn, 42
@DateBridge, 66
@DocumentId, 37
@DynamicBoost, 80
@Entity, 17
@Field, 18

parametry, 38

@FieldBridge, 68
@FullTextFilterDef, 87
@GeneratedValue, 18
@Id, 18, 37
@Indexed, 18–19, 40
@IndexEmbedded, 42

atrybut includePaths, 46

@Key, 85
@ManyToMany, 41
@NumericField, 39–40
@WebServlet, 23

adnotowanie, 19
aktualizacja grupowa, 101–2
aktualizacja indywidualna

dodawanie i aktualizacja, 100
usuwanie, 101

analiza, 73
analizator, 73

definiowany dynamicznie, 77
definiowany statycznie, 75

Apache

Lucene, 10
Maven, 25–26
Solr, 10

API

dla Hibernate ORM, Patrz API mapera

obiektowo-relacyjnego Hibernate

API do tworzenia zapytañ, 52
API Lucene, 113
API mapera obiektowo-relacyjnego

Hibernate, 35, 51–52

API programowe do mapowania, 47–49

archetypy, 26
automatyzacja budowy aplikacji, 25

B

blokowanie dostÚpu do indeksów, 109

D

definicja filtru, 86
dostawca katalogów

opierajÈcy siÚ na pamiÚci RAM, 110
opierajÈcy siÚ na systemie plików, 108–9

dostosowanie encji do Hibernate Search, 18–19
DSL, 24
dzielenie zmiennej na wiele pól, 70–71

E

element

indexNullAs, 66–67
params, 69
store, 90

elementy, 44
EntityIndexingInterceptor, 82

Kup książkę

Poleć książkę

background image

Skorowidz

130

F

fabryka filtrów, 84–85
fasety

dyskretne, 91–92
z zakresami, 93–94

filtrowanie

tokenów, 74
znaków, 73

filtry, 84
fragmentacja indeksu, 102

H

Hibernate Search, 10
Hibernate Search DSL, 24, 54

I

indeksowanie

czÚĂciowe, 46–47
rÚczne, 100
warunkowe, 80–82

IndexingOverride, 82
Infinispan, 120
interceptor, 80

J

Java persistence API, Patrz JPA
JGroups, 120
JMS, 120
JPA, 36, 52

K

klasa

MassIndexer, 101
POJO, 17
SearchMapping, 47–49

klastry nadrzÚdny-podrzÚdny, 119–20, 124

dostawcy katalogów, 119
procesy robocze, 120

klastry proste, 118–19
klucz do filtru, 85
komponenty, 44

SOLR, 73–74

konwersje danych, 66

L

leniwe podejĂcie do pobierania powiÈzanych
encji, 42
Lucene, Patrz Apache Lucene
Luke, 111–12

’

ïÈczenie

wielu zmiennych w jednym polu indeksu, 71
zapytañ, 60–61

M

mapowanie

dat, 66
encji, 35, 65
pola, 38, 62–63

wielokrotne, 39

pól liczbowych, 39–40

Maven, Patrz Apache Maven
menedĝer indeksowania, 105–6
metoda

flushToIndexes, 101
getResultSize, 64
index, 100
limitExecutionTime, 96
must, 60–61
objectToString, 68
purge, 101
purgeAll, 101
setMaxResults, 63
setTimeout, 96
should, 60–61
start, 102
startAndWait, 102
stringToObject, 68

O

obiekt FullTextSession, 23
ograniczanie czasu wykonywania zapytania, 96–97
optymalizacja indeksów, 103

automatyczna, 104
rÚczna, 103

Kup książkę

Poleć książkę

background image

Skorowidz

131

P

ParametrizedBridge, 69
partycjonowanie, 125–26
polecenie $mvn clean package, 33
poprawa wydajnoĂci, 117–18
powiÈzane encje, 40–42
procesy robocze, 106

asynchroniczna aktualizacja indeksów, 107
bufor kolejki, 108
pula wÈtków, 107
synchroniczna aktualizacja indeksów, 107

projekcje, 88

konwertowanie wyników projekcji na obiekty,

89

tworzenie zapytañ, 88
udostÚpnianie pól Lucene do projekcji, 89

próg zgodnoĂci, 56

R

relacja dwustronna miÚdzy encjami, 41

S

segment, 102
skalowanie aplikacji, 118
Solr, Patrz Apache Solr
sortowanie, 62–63
StringBridge, 67, 70
stronicowanie, 63

T

tokenizer, 74
tokenizowanie, 74
transformer, 65

dwukierunkowy, 68
klasy, 71

tworzenie

klasy encji, 16–18
projektu, 26–28
zapytania, 21–25
zapytañ w JPA, 52–53

TwoWayFieldBridge, 72
TwoWayStringBridge, 68, 70

U

uruchamianie aplikacji, 29–33
uĝywanie filtru w zapytaniu, 87

W

wartoĂÊ null, 66–67
wbudowane obiekty, 43–46
wdroĝenie klastra, przykïad, 120–24
wyszukiwanie fasetowe, 91–92

Z

zaleĝnoĂÊ hibernate-entitymanager, 54
zapytanie

boolowskie, 60–61
ïÈczone, 60–61
na podstawie frazy, 58–59
na podstawie sïów kluczowych, 55–56
o zagnieĝdĝone encje, 43
oparte na zakresie, 59–60
rozmyte, 56
z wieloznacznikami, 57–58
zaawansowane, 83

zwiÚkszanie waĝnoĂci pól na czas wyszukiwania,
95–96
zwiÚkszanie waĝnoĂci wyników wyszukiwania, 78

dynamicznego, 79
statycznego, 78

Kup książkę

Poleć książkę

background image

Skorowidz

132

Kup książkę

Poleć książkę

background image
background image

Wyszukiwarka

Podobne podstrony:
Hibernate Search Skuteczne wyszukiwanie 3
Hibernate Search Skuteczne wyszukiwanie
Optymalizacja serwisow internetowych Tajniki szybkosci, skutecznosci i wyszukiwarek
(ebook www zlotemysli pl) skuteczne wyszukiwanie ofert pracy fragment 33PJSJPDZG5ITVHGBX6UR3UA7LOZSN
darmowy ebook skuteczne wyszukiwanie ofert pracy praca, jak znalezc i zarobic prawdziwe pieniadze
Optymalizacja serwisow internetowych Tajniki szybkosci, skutecznosci i wyszukiwarek
Skuteczne wyszukiwanie ofert pracy 2
Skuteczne wyszukiwanie ofert pracy [exploder pl] (osloskop net)
Jak skutecznie wyszukiwac sterowniki pod Windows XP
skuteczne wyszukiwanie ofert pracy
Skuteczne wyszukiwanie ofert pracy 2
informatyka optymalizacja serwisow internetowych tajniki szybkosci skutecznosci i wyszukiwarek andre
Miłosz Młynarz Skuteczne wyszukiwanie ofert pracy
Skuteczne wyszukiwanie ofert pracy
skuteczne wyszukiwanie ofert pracy

więcej podobnych podstron