/* * Hibernate Search, full-text search for your domain model * * License: GNU Lesser General Public License (LGPL), version 2.1 or later * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.demos; import static org.fest.assertions.Assertions.assertThat; import java.util.Arrays; import java.util.Date; import java.util.GregorianCalendar; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import org.hibernate.demos.hswithes.model.Character; import org.hibernate.demos.hswithes.model.Publisher; import org.hibernate.demos.hswithes.model.VideoGame; import org.hibernate.search.elasticsearch.ElasticsearchProjectionConstants; import org.hibernate.search.elasticsearch.ElasticsearchQueries; import org.hibernate.search.jpa.FullTextEntityManager; import org.hibernate.search.jpa.FullTextQuery; import org.hibernate.search.jpa.Search; import org.hibernate.search.query.dsl.QueryBuilder; import org.hibernate.transform.BasicTransformerAdapter; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; public class HibernateSearchWithElasticsearchIT extends TestBase { private static EntityManagerFactory emf; @BeforeClass public static void setUpEmf() { emf = Persistence.createEntityManagerFactory( "videoGamePu" ); setUpTestData(); } public static void setUpTestData() { EntityManager em = emf.createEntityManager(); inTransaction( em, tx -> { Publisher samuraiGames = new Publisher( "Samurai Games, Inc.", "12 Main Road" ); Character luigi = new Character( "Luigi", "Plumbing" ); em.persist( luigi ); Character frank = new Character( "Frank", "Sleeping" ); em.persist( frank ); Character dash = new Character( "Dash", "Running" ); em.persist( dash ); // Game 1 VideoGame game = new VideoGame.Builder() .withTitle( "Revenge of the Samurai" ) .withDescription( "The Samurai is mad and takes revenge" ) .withRating( 8 ) .withPublishingDate( new GregorianCalendar( 2005, 11, 5 ).getTime() ) .withPublisher( samuraiGames ) .withCharacters( luigi, dash ) .withTags( "action", "real-time", "anime" ) .build(); em.persist( game ); // Game 2 game = new VideoGame.Builder() .withTitle( "Tanaka's return" ) .withDescription( "The famous Samurai Tanaka returns" ) .withRating( 10 ) .withPublishingDate( new GregorianCalendar( 2011, 2, 13 ).getTime() ) .withPublisher( samuraiGames ) .withCharacters( frank, dash, luigi ) .withTags( "action", "round-based" ) .build(); em.persist( game ); // Game 3 game = new VideoGame.Builder() .withTitle( "Ninja Castle" ) .withDescription( "7 Ninjas live in a castle" ) .withRating( 5 ) .withPublishingDate( new GregorianCalendar( 2007, 3, 7 ).getTime() ) .withPublisher( samuraiGames ) .withCharacters( frank ) .build(); em.persist( game ); } ); em.close(); } @Test public void queryOnSingleField() { EntityManager em = emf.createEntityManager(); inTransaction( em, tx -> { FullTextEntityManager ftem = Search.getFullTextEntityManager( em ); QueryBuilder qb = ftem.getSearchFactory() .buildQueryBuilder() .forEntity( VideoGame.class ) .get(); FullTextQuery query = ftem.createFullTextQuery( qb.keyword().onField( "title" ).matching( "samurai" ).createQuery(), VideoGame.class ); List<VideoGame> videoGames = query.getResultList(); assertThat( videoGames ).onProperty( "title" ).containsExactly( "Revenge of the Samurai" ); } ); em.close(); } @Test public void queryOnMultipleFields() { EntityManager em = emf.createEntityManager(); inTransaction( em, tx -> { FullTextEntityManager ftem = Search.getFullTextEntityManager( em ); QueryBuilder qb = ftem.getSearchFactory() .buildQueryBuilder() .forEntity( VideoGame.class ) .get(); FullTextQuery query = ftem.createFullTextQuery( qb.keyword().onFields( "title", "description").matching( "samurai" ).createQuery(), VideoGame.class ); List<VideoGame> videoGames = query.getResultList(); assertThat( videoGames ).onProperty( "title" ).containsExactly( "Revenge of the Samurai", "Tanaka's return" ); } ); em.close(); } @Test public void wildcardQuery() { EntityManager em = emf.createEntityManager(); inTransaction( em, tx -> { FullTextEntityManager ftem = Search.getFullTextEntityManager( em ); QueryBuilder qb = ftem.getSearchFactory() .buildQueryBuilder() .forEntity( VideoGame.class ) .get(); FullTextQuery query = ftem.createFullTextQuery( qb.keyword().wildcard().onFields( "title", "description").matching( "sam*" ).createQuery(), VideoGame.class ); List<VideoGame> videoGames = query.getResultList(); assertThat( videoGames ).onProperty( "title" ).containsExactly( "Revenge of the Samurai", "Tanaka's return" ); } ); em.close(); } @Test public void rangeQuery() { EntityManager em = emf.createEntityManager(); inTransaction( em, tx -> { FullTextEntityManager ftem = Search.getFullTextEntityManager( em ); QueryBuilder qb = ftem.getSearchFactory() .buildQueryBuilder() .forEntity( VideoGame.class ) .get(); FullTextQuery query = ftem.createFullTextQuery( qb.range() .onField( "rating" ) .from( 2 ) .to( 9 ) .createQuery(), VideoGame.class ); List<VideoGame> videoGames = query.getResultList(); assertThat( videoGames ).onProperty( "title" ).containsOnly( "Revenge of the Samurai", "Ninja Castle" ); } ); em.close(); } @Test public void queryString() { EntityManager em = emf.createEntityManager(); inTransaction( em, tx -> { FullTextEntityManager ftem = Search.getFullTextEntityManager( em ); QueryBuilder qb = ftem.getSearchFactory() .buildQueryBuilder() .forEntity( VideoGame.class ) .get(); FullTextQuery query = ftem.createFullTextQuery( ElasticsearchQueries.fromQueryString( "title:sam* OR description:sam*" ), VideoGame.class ); List<VideoGame> videoGames = query.getResultList(); assertThat( videoGames ).onProperty( "title" ).containsExactly( "Revenge of the Samurai", "Tanaka's return" ); } ); em.close(); } @Test public void projection() { EntityManager em = emf.createEntityManager(); inTransaction( em, tx -> { FullTextEntityManager ftem = Search.getFullTextEntityManager( em ); QueryBuilder qb = ftem.getSearchFactory() .buildQueryBuilder() .forEntity( VideoGame.class ) .get(); FullTextQuery query = ftem.createFullTextQuery( qb.keyword() .onField( "tags" ) .matching( "round-based" ) .createQuery(), VideoGame.class ) .setProjection( "title", "publisher.name", "release" ); Object[] projection = (Object[]) query.getSingleResult(); assertThat( projection[0] ).isEqualTo( "Tanaka's return" ); assertThat( projection[1] ).isEqualTo( "Samurai Games, Inc." ); assertThat( projection[2] ).isEqualTo( new GregorianCalendar( 2011, 2, 13 ).getTime() ); query = ftem.createFullTextQuery( qb.keyword() .onField( "tags" ) .matching( "round-based" ) .createQuery(), VideoGame.class ) .setProjection( ElasticsearchProjectionConstants.SCORE, ElasticsearchProjectionConstants.SOURCE ); projection = (Object[]) query.getSingleResult(); System.out.println( Arrays.toString( projection ) ); } ); em.close(); } @Test public void projectionWithTransformer() { EntityManager em = emf.createEntityManager(); inTransaction( em, tx -> { FullTextEntityManager ftem = Search.getFullTextEntityManager( em ); QueryBuilder qb = ftem.getSearchFactory() .buildQueryBuilder() .forEntity( VideoGame.class ) .get(); FullTextQuery query = ftem.createFullTextQuery( qb.keyword() .onField( "tags" ) .matching( "round-based" ) .createQuery(), VideoGame.class ) .setProjection( "title", "publisher.name", "release" ) .setResultTransformer( new BasicTransformerAdapter() { @Override public VideoGameDto transformTuple(Object[] tuple, String[] aliases) { return new VideoGameDto( (String) tuple[0], (String) tuple[1], (Date) tuple[2] ); } } ); VideoGameDto projection = (VideoGameDto) query.getSingleResult(); assertThat( projection.getTitle() ).isEqualTo( "Tanaka's return" ); assertThat( projection.getPublisherName() ).isEqualTo( "Samurai Games, Inc." ); assertThat( projection.getRelease() ).isEqualTo( new GregorianCalendar( 2011, 2, 13 ).getTime() ); } ); em.close(); } @Test @Ignore public void manualIndexing() { EntityManager em = emf.createEntityManager(); FullTextEntityManager ftem = Search.getFullTextEntityManager( em ); ftem.getTransaction().begin(); VideoGame game = ftem.find( VideoGame.class, 311 ); ftem.index( game ); ftem.getTransaction().commit(); } @AfterClass public static void closeEmf() { emf.close(); } public static class VideoGameDto { private final String title; private final String publisherName; private final Date release; public VideoGameDto(String title, String publisherName, Date release) { this.title = title; this.publisherName = publisherName; this.release = release; } public String getTitle() { return title; } public String getPublisherName() { return publisherName; } public Date getRelease() { return release; } @Override public String toString() { return "VideoGameDto [title=" + title + ", publisherName=" + publisherName + ", release=" + release + "]"; } } }