/*
* 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.search.elasticsearch.test;
import static org.fest.assertions.Assertions.assertThat;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.TermQuery;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.search.FullTextSession;
import org.hibernate.search.Search;
import org.hibernate.search.annotations.Analyze;
import org.hibernate.search.annotations.Analyzer;
import org.hibernate.search.annotations.AnalyzerDef;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.annotations.Store;
import org.hibernate.search.elasticsearch.testutil.TestElasticsearchClient;
import org.hibernate.search.test.SearchTestBase;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import com.google.gson.JsonParser;
/**
* Test the use of Elasticsearch built-in and server-defined, custom analyzers,
* <strong>without</strong> using {@link AnalyzerDef}.
*
* @author Davide D'Alto
*/
public class ElasticsearchAnalyzerIT extends SearchTestBase {
@Rule
public TestElasticsearchClient elasticsearchClient = new TestElasticsearchClient();
@Override
@Before
public void setUp() throws Exception {
// Make sure automatically created indexes will have the "server-defined-custom-analyzer" analyzer definition
elasticsearchClient.template( "server-defined-custom-analyzer" )
.create(
"*",
new JsonParser().parse(
"{"
+ "'index': {"
+ "'analysis': {"
+ "'analyzer': {"
+ "'server-defined-custom-analyzer': {"
+ "'char_filter': ['html_strip'],"
+ "'tokenizer': 'standard',"
+ "'filter': ['server-defined-custom-filter', 'lowercase']"
+ "}"
+ "},"
+ "'filter': {"
+ "'server-defined-custom-filter': {"
+ "'type': 'stop',"
+ "'stopwords': ['test1', 'close']"
+ "}"
+ "}"
+ "}"
+ "}"
+ "}"
)
.getAsJsonObject()
);
super.setUp();
}
@Test
public void testDefaultAnalyzer() throws Exception {
try ( Session session = openSession() ) {
FullTextSession fullTextSession = Search.getFullTextSession( session );
Tweet tweet = new Tweet();
tweet.setDefaultTweet( "the Foxes" );
tweet( session, tweet );
TermQuery query = new TermQuery( new Term( "defaultTweet", "fox" ) );
@SuppressWarnings("unchecked")
List<Tweet> list = fullTextSession.createFullTextQuery( query ).list();
assertThat( list ).as( "It should not find the tweet without a defined analyzer" ).isEmpty();
}
}
@Test
public void testEnglishBuiltInAnalyzer() throws Exception {
try ( Session session = openSession() ) {
FullTextSession fullTextSession = Search.getFullTextSession( session );
Tweet tweet = new Tweet();
tweet.setEnglishTweet( "the Foxes" );
tweet( session, tweet );
TermQuery query = new TermQuery( new Term( "englishTweet", "fox" ) );
@SuppressWarnings("unchecked")
List<Tweet> list = fullTextSession.createFullTextQuery( query ).list();
assertThat( list ).onProperty( "englishTweet" ).containsExactly( tweet.getEnglishTweet() );
}
}
@Test
public void testWhitespaceBuiltInAnalyzer() throws Exception {
try ( Session session = openSession() ) {
FullTextSession fullTextSession = Search.getFullTextSession( session );
Tweet tweet = new Tweet();
tweet.setWhitespaceTweet( "What does the fox say?" );
tweet( session, tweet );
TermQuery query = new TermQuery( new Term( "whitespaceTweet", "fox" ) );
@SuppressWarnings("unchecked")
List<Tweet> list = fullTextSession.createFullTextQuery( query, Tweet.class ).list();
assertThat( list ).onProperty( "whitespaceTweet" ).containsExactly( tweet.getWhitespaceTweet() );
}
}
@Test
public void testCustomAnalyzer() throws Exception {
try ( Session session = openSession() ) {
FullTextSession fullTextSession = Search.getFullTextSession( session );
Tweet tweet = new Tweet();
tweet.setCustomTweet( "close OPEN SOURCE test1" );
tweet( session, tweet );
@SuppressWarnings("unchecked")
List<Tweet> expectedResult = fullTextSession.createFullTextQuery( termQuery( "customTweet", "open" ), Tweet.class ).list();
assertThat( expectedResult ).onProperty( "customTweet" ).containsExactly( tweet.getCustomTweet() );
@SuppressWarnings("unchecked")
List<Tweet> expectedEmpty = fullTextSession.createFullTextQuery( termQuery( "customTweet", "CLOSE" ), Tweet.class ).list();
assertThat( expectedEmpty ).as( "Custom analyzer or filter not applied" ).isEmpty();
}
}
@Test
public void testMultipleFieldsCustomAnalyzer() throws Exception {
try ( Session session = openSession() ) {
FullTextSession fullTextSession = Search.getFullTextSession( session );
Tweet tweet = new Tweet();
tweet.setMultipleTweets( "close OPEN SOURCE test1" );
tweet( session, tweet );
@SuppressWarnings("unchecked")
List<Tweet> expectedResult = fullTextSession.createFullTextQuery( termQuery( "tweetWithCustom", "open" ), Tweet.class ).list();
assertThat( expectedResult ).onProperty( "multipleTweets" ).containsExactly( tweet.getMultipleTweets() );
@SuppressWarnings("unchecked")
List<Tweet> expectedEmpty = fullTextSession.createFullTextQuery( termQuery( "tweetWithCustom", "CLOSE" ), Tweet.class ).list();
assertThat( expectedEmpty ).as( "Custom analyzer or filter not applied" ).isEmpty();
}
}
@Test
public void testMultipleFieldIgnoreAnalyzer() throws Exception {
try ( Session session = openSession() ) {
FullTextSession fullTextSession = Search.getFullTextSession( session );
Tweet tweet = new Tweet();
tweet.setMultipleTweets( "close OPEN SOURCE test1" );
tweet( session, tweet );
@SuppressWarnings("unchecked")
List<Tweet> expectedResult = fullTextSession.createFullTextQuery( termQuery( "tweetNotAnalyzed", "close OPEN SOURCE test1" ), Tweet.class ).list();
assertThat( expectedResult ).onProperty( "multipleTweets" ).containsExactly( tweet.getMultipleTweets() );
}
}
private TermQuery termQuery(String fld, String text) {
TermQuery query = new TermQuery( new Term( fld, text ) );
return query;
}
private void tweet(Session session, Tweet tweet) {
Transaction tx = session.beginTransaction();
session.persist( tweet );
tx.commit();
session.clear();
}
@Entity
@Indexed(index = "tweet")
public static class Tweet {
@Id
@GeneratedValue
private Integer id;
@Field
@Analyzer(definition = "english")
private String englishTweet;
@Field
@Analyzer(definition = "whitespace")
private String whitespaceTweet;
@Field
// Defined in the elasticsearch.yml configuration file
@Analyzer(definition = "server-defined-custom-analyzer")
private String customTweet;
@Field(name = "tweetNotAnalyzed", analyze = Analyze.NO, store = Store.YES)
@Field(name = "tweetWithCustom", analyzer = @Analyzer(definition = "server-defined-custom-analyzer") )
private String multipleTweets;
private String defaultAnalyzer;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getEnglishTweet() {
return englishTweet;
}
public void setEnglishTweet(String englishTweet) {
this.englishTweet = englishTweet;
}
public String getWhitespaceTweet() {
return whitespaceTweet;
}
public void setWhitespaceTweet(String whitespaceTweet) {
this.whitespaceTweet = whitespaceTweet;
}
public String getCustomTweet() {
return customTweet;
}
public void setCustomTweet(String customTweet) {
this.customTweet = customTweet;
}
public String getDefaultAnalyzer() {
return defaultAnalyzer;
}
public void setDefaultTweet(String defaultAnalyzer) {
this.defaultAnalyzer = defaultAnalyzer;
}
public String getMultipleTweets() {
return multipleTweets;
}
public void setMultipleTweets(String multipleMessage) {
this.multipleTweets = multipleMessage;
}
@Override
public String toString() {
return "[" + englishTweet + ", " + whitespaceTweet + "]";
}
}
@Override
public Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{ Tweet.class };
}
}