May 2010 - Hibernate search
Upcoming SlideShare
Loading in...5
×
 

May 2010 - Hibernate search

on

  • 2,332 views

Hibernate Search - Sanne Grinovero

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

Statistics

Views

Total Views
2,332
Views on SlideShare
2,085
Embed Views
247

Actions

Likes
3
Downloads
35
Comments
2

4 Embeds 247

http://pronetics.wordpress.com 194
http://www.pro-netics.com 46
http://www.slideshare.net 5
url_unknown 2

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

May 2010 - Hibernate search May 2010 - Hibernate search Presentation Transcript

  • Java Users Group Sardegna e JBoss Users group Roma Cagliari 29 Maggio 2010 HIBERNATE SEARCH “Gooooglizzare” efficacemente il domain model Sanne Grinovero Team Hibernate per Sourcesense
  • Example database
  • 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!
  • Idea:
  • 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”
  • SQL è il martello: String nomeAutore = “Fabrizio De André” String nomeProdotto = “Nuvole barocche” List<Prodotti> list = s.createQuery( “ ...? “ );
  • 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( “ ...? “ );
  • 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( “ ...???? “ );
  • 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ù?
  • Come sarebbe Google se vi restituisse i siti in ordine alfabetico?
  • Come sarebbe Google se vi restituisse i siti in ordine alfabetico? “hibernate” About 8,320,000 results (0.20 seconds)
  • 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.
  • Lucene ● Similitudine tra termini e documenti ● Sinonimi ● Stemming ● Stopwords ● TermVectors ● MoreLikeThis ● Faceted Search ● Velocità e scalabilità orizzontale ● ... e naturalmente ricerche full-text.
  • Similitudine Cagliari ⁓ càliari Cagliari ⁓ cag agl gli lia ari Cagliari ⁓ CGRI ● N-Grams (distanza di editing) ● Fonetico (Soundex™) ● Altro... definibile secondo necessità
  • Lucene: Sinonimi (o quasi) giornale ⁓ periodico ⁓ quotidiano ● Applicabile a “index time” ● a “query time” ● Necessita di un vocabolario ● Integrabile con vari vocabolari (WordNet)
  • Lucene: Stemming parliamone ⁓ parlo Velocemente ⁓ velocità Le grammatiche di stemming sono disponibili per un'ampia scelta di lingue, spesso free.
  • 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.
  • 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?
  • Differenze strutturali dell'informazione
  • Incoerenze architetturali
  • 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
  • Come usare Hibernate Search @Entity public 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; } ...
  • Come usare Hibernate Search @Entity @Indexed public 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; } ...
  • Come usare Hibernate Search @Entity @Indexed public 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; } ...
  • Come usare Hibernate Search @Entity @Indexed public 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; } ...
  • Come usare Hibernate Search @Entity @Indexed public 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; } ...
  • Altro esempio @Entity @Entity public class Author { public class Book { @Id @GeneratedValue private Integer id; private Integer id; private String title; private String name; } @OneToMany private Set<Book> books; }
  • Struttura dell'indice @Entity @Indexed @Entity public class Author { public class Book { @Id @GeneratedValue private Integer id; private Integer id; @Field(store=Store.YES) @Field(store=Store.YES) private String title; private String name; } @OneToMany @IndexedEmbedded private Set<Book> books; }
  • Codice di Query: 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(); TotalNbrOfResults= 8.320.000 (0.20 seconds)
  • Risultati ● Pojo gestiti! ● Paginazione ● .setMaxResults( 20 ).setFirstResult( 100 ); ● Restrizioni per tipo ● .createQuery( luceneQuery, A.class, B.class, ..); ● Projection ● Result mapping
  • Demo / Tests org.hibernate.search.test.filter.FilterTest org.hibernate.search.test.compression.CompressionTest
  • Filtri @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 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();
  • 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; ...
  • Altro... ● @Boost e @DynamicBoost ● @AnalyzerDiscriminator ● @DateBridge(resolution=Resolution.MINUTE) ● @ClassBridge e @FieldBridge ● @Similarity ● Automatic Index optimization
  • Clustering per coda
  • Clustering per distributed store
  • Mass (re)indexing fullTextSession.createIndexer()    .startAndWait();
  • Mass (re)indexing fullTextSession.createIndexer(Hotel.class,    Person.class,Car.class)    .threadsForSubsequentFetching( 8 )    .threadsToLoadObjects( 4 )    .batchSizeToLoadObjects( 30 )    .startAndWait();
  • 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
  • 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