Hibernate und Elasticsearch

Werbung
1
Hibernate und Elasticsearch
Von 0 auf 100 in 40 Minuten
Gunnar Morling, Red Hat
2
Gunnar Morling
Opensource-Softwareentwickler bei Red Hat
Div. Hibernate-Projekte
Spec Lead für Bean Validation 2.0
Andere Projekte: ModiTect, MapStruct
[email protected]
@gunnarmorling
http://in.relation.to/gunnar-morling/
3
"Wir brauchen eine Suchfunktion"
Sehr gute Treffer
Smart (fehlertolerant...)
4
Wie umsetzen?
SQL hat LIKE?
SELECT *
FROM PRODUCT p
WHERE
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
...
;
5
Wie umsetzen?
Ja, aber...
Flexionen, Normalisierung, Stop-Worte
Synonyme, Abkürzungen
Unscharfe Suche
Ergebnissortierung
6
Wie umsetzen?
Ja, aber...
Flexionen, Normalisierung, Stop-Worte
Synonyme, Abkürzungen
Unscharfe Suche
Ergebnissortierung
SELECT *
FROM PRODUCT p
WHERE
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
...
;
7
Wie umsetzen?
Invertierter Index
Text zerlegen ("tokenisation")
Index erstellen: Token → Enthaltende Dokumente
Suche: Relevanzbasierte Sortierung
8
Lucene + Elasticsearch
Apache 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
9
Index-Synchronisation?!
???
JPA-Anwendung
10
Index-Synchronisation?!
Indexstruktur synchron halten
Update des Index in Elasticsearch bei Datenänderungen
JSON erzeugen
Typumwandlungen
Assoziationen/Denormalisierungen
Mapping von Suchergebnissen
11
Hibernate Search
Anwendung
ORM
Hibernate
Search
DB
Volltext-Index
12
Hibernate Search
Integriert Hibernate und Lucene
Traditionell: Eigene Verwaltung des Lucene-Index
Dateisystem
Infinispan
Unter Java SE and EE
Kein neues Projekt :)
13
Beispiel
14
Ein Beispiel
Entity-Modell
15.1
Demo
15.2
Ein Beispiel
pom.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.3
Ein Beispiel
persistence.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.4
Ein Beispiel
Root-Entität
curl -v -XGET 'host/videogame/_search?pretty=true' \
-d '{ "query" : { "match_all" : {} } }'
@Entity
@Indexed(index = "videogame")
public class VideoGame {
@Id
@GeneratedValue
public long id;
@Field()
public String title;
@Field
public String description;
@Field
public int rating;
{
...
"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"
}
},
...
]
}
@Field(name="release")
public Date publishingDate;
...
}
}
15.5
Ein Beispiel
Embeddable und ElementCollection
@Entity
@Indexed(index = "videogame")
public class VideoGame {
{
"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"
}
@ManyToOne
@IndexedEmbedded
public Publisher publisher;
@ElementCollection
@Field
@IndexedEmbedded
public List<String> tags;
...
}
}
@Entity
public class Publisher {
@Field
public String name;
@Field
public String address;
...
15.6
Ein Beispiel
Eingebettete Assoziation
@Entity
@Indexed(index = "videogame")
public class VideoGame {
{
"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"
}
]
@ManyToMany
@IndexedEmbedded
public List<Character> characters;
...
}
@Entity
public class Character {
@Field
public String nickName;
@Field
public String specialPower;
...
}
}
16
Abfragen
Hibernate 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
);
17
Native Abfragen
JSON-Syntax
FullTextQuery query = ftem.createFullTextQuery(
ElasticsearchQueries.fromJson(
"{" +
"'query': {" +
"'bool' : {" +
"'must' : [" +
"{ 'match' : { 'title' : 'samurai' } }," +
"{ 'match' : { 'publisher.name' : 'games' } }" +
"]" +
"} } }"
),
VideoGame.class );
18
Projektionen
FullTextQuery query = ftem.createFullTextQuery(
ElasticsearchQueries.fromQueryString(
"title:sam* OR description:sam*"
),
VideoGame.class
)
.setProjection( "title", "publisher.name", "release" );
19
Vorteile
Date und Index synchron
Sichere, automatische Index-Updates
Automatisches Mapping
JSON-Mapping
Typkonvertierungen
Transparente Denormalisierung
Managed Entities aus Abfragen
Gute Performance (Bulk-Requests)
20
Vorteile
Entkopplung
Einfache Konfiguration mittels Annotationen
Keine direkten Aufrufe des ES API nötig
Einfacher Backendwechsel
Entkopplung von Komponenten zur Laufzeit
21
Was sonst noch?
Analyzer
Faceting
Re-indexing per Batch
Mandatenfähigkeit
Konfigurations-DSL
Support für Java 8 / Hibernate ORM 5.2
22
Status
Tech Preview in Hibernate Search 5.6/5.7
Indexierung verschiedenster Feldtypen, Embeddables etc.
Diverse Abfrage-Möglichkeiten
Viele Tests der bestehenden Testsuite erfolgreich
23
Nächste Schritte
5.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
24
Feedback
Website: hibernate.org/search
Beispielprojekt: github.com/hibernate/hibernate-demos
Hibernate-Blog: in.relation.to
25
Herunterladen