May 2010 - Hibernate search

43
HIBERNATE SEARCH Java Users Group Sardegna e JBoss Users group Roma Cagliari 29 Maggio 2010 “Gooooglizzare” efficacemente il domain model Sanne Grinovero Team Hibernate per Sourcesense

description

Hibernate Search - Sanne Grinovero 29/05/2010 - Jug Sardegna - JBoss User Group Roma

Transcript of May 2010 - Hibernate search

Page 1: May 2010 - Hibernate search

HIBERNATE SEARCH

Java Users Group Sardegna e JBoss Users group RomaCagliari 29 Maggio 2010

“Gooooglizzare” efficacementeil domain model

Sanne GrinoveroTeam Hibernate per Sourcesense

Page 2: May 2010 - Hibernate search

Example database

Page 3: May 2010 - Hibernate search

Search engine: obiettivi

● Chi cerca non sa cosa sta cercando:● non è in grado di inserire l'ID dell'oggetto che

desidera recuperare● non conosce il contenuto esatto del documento

● Interfaccia tipica:● Form complesse con molti campi● Testo libero!

Page 4: May 2010 - Hibernate search

Idea:

Page 5: May 2010 - Hibernate search

Specifiche “probabili”

● Campo unico● Nome autore e/o nome prodotto● Nome e cognome dell'autore, nomi composti

● Innanzitutto i match principali● prodotti che corrispondono sia per nome che per

nome autore devono venire per primi● Nomi completi di prodotto prima di nomi parziali

– “portatile mac” > “portatile”

Page 6: May 2010 - Hibernate search

SQL è il martello:

String nomeAutore = “Fabrizio De André”String nomeProdotto = “Nuvole barocche”List<Prodotti> list = s.createQuery( “ ...? “ );

Page 7: May 2010 - Hibernate search

SQL è il martello:

String nomeAutore = “Fabrizio De André”String nomeProdotto = “Nuvole barocche”List<Prodotti> list = s.createQuery( “ ...? “ );

String nomeAutore = “DeAndré Fabrizio”String nomeProdotto = “Nuvole barocche”List<Prodotti> list = s.createQuery( “ ...? “ );

Page 8: May 2010 - Hibernate search

SQL è il martello:

String nomeAutore = “Fabrizio De André”String nomeProdotto = “Nuvole barocche”List<Prodotti> list = s.createQuery( “ ...? “ );

String nomeAutore = “DeAndré Fabrizio”String nomeProdotto = “Nuvole barocche”List<Prodotti> list = s.createQuery( “ ...? “ );

String query = “F. de André nuvole barocche”List<Prodotti> list = s.createQuery( “ ...???? “ );

Page 9: May 2010 - Hibernate search

E se poi “precisano” le specifiche?

● Similitudine:● hybernatʻ ʼ

● Prossimità e sinonimi:● 'JPA' o 'Java Persistence API'

● Rilevanza:● Più parole simili, o “più simili”● Un termine nel titolo “vale” di più?

Page 10: May 2010 - Hibernate search

Come sarebbe Google se vi restituisse i siti in ordine alfabetico?

Page 11: May 2010 - Hibernate search

Come sarebbe Google se vi restituisse i siti in ordine alfabetico?

“hibernate”About 8,320,000 results (0.20 seconds)

Page 12: May 2010 - Hibernate search

Lucene

● Progetto open source Apache™,● nella “top 10” dei più scaricati.● Community molto attiva.

● Un'implementazione di indice invertito all'avanguaria, costantemente aggiornato allo stato dell'arte del settore.

● Principalmente in Java ma portato in vari altri linguaggi.● Si trovano innumerevoli estensioni open source, ad

esempio per il supporto ottimale di tutte le lingue occidentali.

Page 13: May 2010 - Hibernate search

Lucene

● Similitudine tra termini e documenti

● Sinonimi

● Stemming

● Stopwords

● TermVectors

● MoreLikeThis

● Faceted Search

● Velocità e scalabilità orizzontale

● ... e naturalmente ricerche full-text.

Page 14: May 2010 - Hibernate search

Similitudine

● N-Grams (distanza di editing)● Fonetico (Soundex™)● Altro... definibile secondo necessità

Cagliari ⁓ càliariCagliari ⁓ cag agl gli lia ari

Cagliari ⁓ CGRI

Page 15: May 2010 - Hibernate search

Lucene: Sinonimi (o quasi)

● Applicabile a “index time”● a “query time”● Necessita di un vocabolario● Integrabile con vari vocabolari (WordNet)

giornale ⁓ periodico ⁓ quotidiano

Page 16: May 2010 - Hibernate search

Lucene: Stemming

Le grammatiche di stemming sono disponibili per un'ampia scelta di lingue, spesso free.

parliamone ⁓ parloVelocemente ⁓ velocità

Page 17: May 2010 - Hibernate search

Lucene: Stopwords

● Rimuovono “rumore di fondo” e termini di disturbo dall'indice: una ricerca per “non e queste al per da” non da indizi su cosa l'utente stia cercando.

Page 18: May 2010 - Hibernate search

Può sembrare facile

● La struttura di un indice è profondamente diversa da un modello relazionale.

● L'indice e il database devono rimanere in coerenza, immediata o eventuale.● Incoerenza: di quale vi fidate?

● Cosa restituiscono le query?

Page 19: May 2010 - Hibernate search

Differenze strutturali dell'informazione

Page 20: May 2010 - Hibernate search

Incoerenze architetturali

Page 21: May 2010 - Hibernate search
Page 22: May 2010 - Hibernate search

Come integrare Hibernate Search

● Aggiungere hibernate-search al classpath e dipendenze<dependency>

   <groupId>org.hibernate</groupId>

   <artifactId>hibernate­search</artifactId>

   <version>3.2.0.Final</version>

</dependency>

● Il resto è opzionale:

● Dove mettere l'indice● Estensioni● Parametri per le performance● Mapping più sofisticati● Clustering

Page 23: May 2010 - Hibernate search

Come usare Hibernate Search@Entitypublic class Essay {   @Id   public Long getId() { return id; }

   public String getSummary() { return summary; }   @Lob    public String getText() { return text; }   @ManyToOne    public Author getAuthor() { return author; }...

Page 24: May 2010 - Hibernate search

Come usare Hibernate Search@Entity @Indexedpublic class Essay {   @Id   public Long getId() { return id; }

   public String getSummary() { return summary; }   @Lob    public String getText() { return text; }   @ManyToOne    public Author getAuthor() { return author; }...

Page 25: May 2010 - Hibernate search

Come usare Hibernate Search@Entity @Indexedpublic class Essay {   @Id   public Long getId() { return id; }   @Field   public String getSummary() { return summary; }   @Lob    public String getText() { return text; }   @ManyToOne    public Author getAuthor() { return author; }...

Page 26: May 2010 - Hibernate search

Come usare Hibernate Search@Entity @Indexedpublic class Essay {   @Id   public Long getId() { return id; }   @Field   public String getSummary() { return summary; }   @Lob @Field @Boost(0.8)   public String getText() { return text; }   @ManyToOne    public Author getAuthor() { return author; }...

Page 27: May 2010 - Hibernate search

Come usare Hibernate Search@Entity @Indexedpublic class Essay {   @Id   public Long getId() { return id; }   @Field   public String getSummary() { return summary; }   @Lob @Field @Boost(0.8)   public String getText() { return text; }   @ManyToOne @IndexedEmbedded    public Author getAuthor() { return author; }...

Page 28: May 2010 - Hibernate search

@Entitypublic class Author {

@Id @GeneratedValueprivate Integer id;private String name;@OneToManyprivate Set<Book> books;

}

@Entitypublic class Book { private Integer id; private String title;}

Altro esempio

Page 29: May 2010 - Hibernate search

@Entity @Indexedpublic class Author {

@Id @GeneratedValueprivate Integer id;

@Field(store=Store.YES)private String name;@OneToMany

@IndexedEmbeddedprivate Set<Book> books;

}

@Entitypublic class Book { private Integer id; @Field(store=Store.YES) private String title;}

Struttura dell'indice

Page 30: May 2010 - Hibernate search

String[] productFields = {"summary", "author.name"};

QueryParser parser = new MultiFieldQueryParser(productFields,   new StandardAnalyzer() );

Query luceneQuery = parser.parse(searchQuery);

FullTextEntityManager ftEm =   Search.getFullTextEntityManager(entityManager);

FullTextQuery query =   ftEm.createFullTextQuery(luceneQuery,Product.class );

List<Essay> items = query.setMaxResults(100).getResultList();

int totalNbrOfResults = query.getResultSize();

Codice di Query:

TotalNbrOfResults= 8.320.000(0.20 seconds)

Page 31: May 2010 - Hibernate search

Risultati

● Pojo gestiti!● Paginazione

● .setMaxResults( 20 ).setFirstResult( 100 );

● Restrizioni per tipo● .createQuery( luceneQuery, A.class, B.class, ..);

● Projection● Result mapping

Page 32: May 2010 - Hibernate search

Demo / Testsorg.hibernate.search.test.filter.FilterTest

org.hibernate.search.test.compression.CompressionTest

Page 33: May 2010 - Hibernate search
Page 34: May 2010 - Hibernate search

@Indexed @Entity@FullTextFilterDefs( {   @FullTextFilterDef(name = "disponibiliSubito", impl =       ProdDisponibileFilter.class, cache = FilterCacheModeType.NONE),   @FullTextFilterDef(name = "security", impl = SecurityFilterFactory.class, cache = FilterCacheModeType.INSTANCE_AND_DOCIDSETRESULTS)})public class Prodotto {   ...

Filtri

Page 35: May 2010 - Hibernate search

Filtri

FullTextQuery ftQuery = s // s è di tipo FullTextSession

   .createFullTextQuery( query, Prodotto.class )

   .enableFullTextFilter( "vietatoMinori" )

   .enableFullTextFilter( "offerteDelGiorno" )

      .setParameter( "giorno", “20100529” )

   .enableFullTextFilter( "disponibiliSubito" )

      .setParameter( "sede", "Cagliari" );

List<Prodotto> risultati = ftQuery.list();

Page 36: May 2010 - Hibernate search

Analizzatori custom@Entity @Indexed

@AnalyzerDef(name = "italianAnalyzer",tokenizer = @TokenizerDef(factory=StandardTokenizerFactory.class),filters = {

@TokenFilterDef(factory = LowerCaseFilterFactory.class),

@TokenFilterDef(factory = SnowballPorterFilterFactory.class,

params = {@Parameter(name = "language", value = "Italian")})

})

public class Book {

@Field(index=Index.TOKENIZED, store=Store.NO)

@Analyzer(definition = "italianAnalyzer")

private String title;

...

Page 37: May 2010 - Hibernate search

Altro...

● @Boost e @DynamicBoost● @AnalyzerDiscriminator● @DateBridge(resolution=Resolution.MINUTE)● @ClassBridge e @FieldBridge● @Similarity● Automatic Index optimization

Page 38: May 2010 - Hibernate search

Clustering per coda

Page 39: May 2010 - Hibernate search

Clustering per distributed store

Page 40: May 2010 - Hibernate search

Mass (re)indexingfullTextSession.createIndexer()   .startAndWait();

Page 41: May 2010 - Hibernate search

Mass (re)indexing

fullTextSession.createIndexer(Hotel.class,   Person.class,Car.class)   .threadsForSubsequentFetching( 8 )   .threadsToLoadObjects( 4 )   .batchSizeToLoadObjects( 30 )   .startAndWait();

Page 42: May 2010 - Hibernate search

Futuro prossimo

● Astrazione delle query Lucene● Performance migliorate

● NumericField● FieldCache

● Indicizzazione di Pojo non gestiti da Hibernate● Infinispan “automagic” clustering● Ulteriori opzioni sul MassIndexer● Mapping dinamico

Page 43: May 2010 - Hibernate search

Domande?

http://search.hibernate.org● Hibernate Search in Action

http://lucene.apache.org● Lucene In Action (2°ed)

http://in.relation.to

http://forum.hibernate.org

twitter.com/SanneGrinovero

www.sourcesense.com