Gunnar MorlingOpensource-Softwareentwickler bei Red Hat
Div. Hibernate-Projekte
Spec Lead für Bean Validation 2.0
Andere Projekte: ModiTect, MapStruct
@gunnarmorling
http://in.relation.to/gunnar-morling/
2
Wie umsetzen?SQL hat LIKE?
SELECT *FROM PRODUCT pWHERE LOWERCASE(p.title) LIKE %:1% OR LOWERCASE(p.title) LIKE %:2% OR LOWERCASE(p.title) LIKE %:3% OR LOWERCASE(p.description) LIKE %:1% OR LOWERCASE(p.description) LIKE %:2% OR LOWERCASE(p.description) LIKE %:3% OR ...;
4
Wie umsetzen?Ja, aber...
Flexionen, Normalisierung, Stop-Worte
Synonyme, Abkürzungen
Unscharfe Suche
Ergebnissortierung
5
Wie umsetzen?Ja, aber...
Flexionen, Normalisierung, Stop-Worte
Synonyme, Abkürzungen
Unscharfe Suche
Ergebnissortierung SELECT *FROM PRODUCT pWHERE LOWERCASE(p.title) LIKE %:1% OR LOWERCASE(p.title) LIKE %:2% OR LOWERCASE(p.title) LIKE %:3% OR LOWERCASE(p.description) LIKE %:1% OR LOWERCASE(p.description) LIKE %:2% OR LOWERCASE(p.description) LIKE %:3% OR ...;
6
Wie umsetzen?Invertierter Index
Text zerlegen ("tokenisation")
Index erstellen: Token → Enthaltende Dokumente
Suche: Relevanzbasierte Sortierung
7
Lucene + ElasticsearchApache Lucene
DIE Java-Library für Volltextsuche
Feature-reich, anpassbar
Hohe Performanz
Elasticsearch
"Search as a Service"
Basiert auf Lucene
Scale-out Architektur
REST API
8
Index-Synchronisation?!Indexstruktur synchron halten
Update des Index in Elasticsearch bei Datenänderungen
JSON erzeugen
Typumwandlungen
Assoziationen/Denormalisierungen
Mapping von Suchergebnissen
10
Hibernate SearchIntegriert Hibernate und Lucene
Traditionell: Eigene Verwaltung des Lucene-Index
Dateisystem
Infinispan
Unter Java SE and EE
Kein neues Projekt :)
12
Ein Beispielpom.xml
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-search-orm</artifactId> <version>5.7.0.Final</version></dependency><dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-search-elasticsearch</artifactId> <version>5.7.0.Final</version></dependency>
15.2
Ein Beispielpersistence.xml
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.1">
<persistence-unit name="videoGamePu" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> <properties> <property name="hibernate.connection.url" value="..." />
<property name="hibernate.search.default.indexmanager" value="elasticsearch" />
<property name="hibernate.search.default.elasticsearch.host" value="http://127.0.0.1:9200" />
<property name="h.s.default.elasticsearch.index_schema_management_strategy" value="CREATE" /> </properties> </persistence-unit></persistence>
15.3
Ein BeispielRoot-Entität
@Entity@Indexed(index = "videogame")public class VideoGame {
@Id @GeneratedValue public long id;
@Field() public String title;
@Field public String description;
@Field public int rating;
@Field(name="release") public Date publishingDate;
...}
curl -v -XGET 'host/videogame/_search?pretty=true' \ -d '{ "query" : { "match_all" : {} } }'
{ ... "hits": [ { "_index": "videogame", "_type": "org.hibernate. ... .VideoGame", "_id": "5", "_score": 1.0, "_source": { "rating": 8, "release": "2005-12-04T23:00:00Z", "description": "The Samurai is...", "title": "Revenge of the Samurai" } }, ... ]}
}
15.4
Ein BeispielEmbeddable und ElementCollection
@Entity@Indexed(index = "videogame")public class VideoGame {
@ManyToOne @IndexedEmbedded public Publisher publisher;
@ElementCollection @Field @IndexedEmbedded public List<String> tags;
...}
{ "rating": 8, "description": "The Samurai is mad and takes revenge", "release": "2005-12-04T23:00:00Z", "title": "Revenge of the Samurai", "tags": [ "action", "real-time", "anime" ], "publisher": { "name": "Samurai Games, Inc.", "address": "12 Main Road" }}
@Entitypublic class Publisher {
@Field public String name;
@Field public String address;
...
15.5
Ein BeispielEingebettete Assoziation
@Entity@Indexed(index = "videogame")public class VideoGame {
@ManyToMany @IndexedEmbedded public List<Character> characters;
...}
{ "rating": 5, "description": "7 Ninjas live in a castle", "release": "2007-04-06T22:00:00Z", "title": "Ninja Castle", "publisher": { "name": "Samurai Games, Inc.", "address": "12 Main Road" }, "characters": [ { "nickName": "Frank", "specialPower": "Sleeping" }, { "nickName": "Dash", "specialPower": "Running" }, { "nickName": "Luigi", "specialPower": "Plumbing" } ]}
@Entitypublic class Character {
@Field public String nickName;
@Field public String specialPower; ...}
15.6
AbfragenHibernate Search Query DSL
Weitere: wildcard, range, boolean, fuzzy, phrase, spatial
FullTextQuery query = ftem.createFullTextQuery( qb.spatial() .onField( "location" ) .within( 100, Unit.KM ) .ofLatitude( 24.0d ) .andLongitude( 32.0d ) .createQuery(), Restaurant.class);
16
FullTextQuery query = ftem.createFullTextQuery( ElasticsearchQueries.fromJson( "{" + "'query': {" + "'bool' : {" + "'must' : [" + "{ 'match' : { 'title' : 'samurai' } }," + "{ 'match' : { 'publisher.name' : 'games' } }" + "]" + "} } }" ), VideoGame.class );
Native AbfragenJSON-Syntax
17
Projektionen
FullTextQuery query = ftem.createFullTextQuery( ElasticsearchQueries.fromQueryString( "title:sam* OR description:sam*" ), VideoGame.class).setProjection( "title", "publisher.name", "release" );
18
VorteileDate und Index synchron
Sichere, automatische Index-Updates
Automatisches Mapping
JSON-Mapping
Typkonvertierungen
Transparente Denormalisierung
Managed Entities aus Abfragen
Gute Performance (Bulk-Requests)
19
VorteileEntkopplung
Einfache Konfiguration mittels Annotationen
Keine direkten Aufrufe des ES API nötig
Einfacher Backendwechsel
Entkopplung von Komponenten zur Laufzeit
20
Was sonst noch?Analyzer
Faceting
Re-indexing per Batch
Mandatenfähigkeit
Konfigurations-DSL
Support für Java 8 / Hibernate ORM 5.2
21
StatusTech Preview in Hibernate Search 5.6/5.7
Indexierung verschiedenster Feldtypen, Embeddables etc.
Diverse Abfrage-Möglichkeiten
Viele Tests der bestehenden Testsuite erfolgreich
22
Nächste Schritte5.8: Unterstützung für Elasticsearch 5
Feedback sammeln in 5.x
Hibernate Search 6
Abstraktion von Lucene in API und SPI
Query DSL verallgemeinern
6.x: Solr-Unterstützung
23
FeedbackWebsite:
Beispielprojekt:
Hibernate-Blog:
hibernate.org/search
github.com/hibernate/hibernate-demos
in.relation.to
24