[hibernate-commits] Hibernate SVN: r19013 - in search/trunk/hibernate-search/src: main/java/org/hibernate/search/impl and 3 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Wed Mar 17 12:30:50 EDT 2010


Author: epbernard
Date: 2010-03-17 12:30:48 -0400 (Wed, 17 Mar 2010)
New Revision: 19013

Added:
   search/trunk/hibernate-search/src/test/java/org/hibernate/search/test/query/dsl/DSLTest.java
   search/trunk/hibernate-search/src/test/java/org/hibernate/search/test/query/dsl/Month.java
Modified:
   search/trunk/hibernate-search/src/main/java/org/hibernate/search/SearchFactory.java
   search/trunk/hibernate-search/src/main/java/org/hibernate/search/impl/SearchFactoryImpl.java
   search/trunk/hibernate-search/src/main/java/org/hibernate/search/query/dsl/v2/QueryBuilder.java
   search/trunk/hibernate-search/src/main/java/org/hibernate/search/query/dsl/v2/QueryContextBuilder.java
   search/trunk/hibernate-search/src/main/java/org/hibernate/search/query/dsl/v2/TermContext.java
   search/trunk/hibernate-search/src/main/java/org/hibernate/search/query/dsl/v2/impl/ConnectedTermContext.java
Log:
HSEARCH-414 test on term, fuzzy and wildcard queries

Modified: search/trunk/hibernate-search/src/main/java/org/hibernate/search/SearchFactory.java
===================================================================
--- search/trunk/hibernate-search/src/main/java/org/hibernate/search/SearchFactory.java	2010-03-16 22:15:51 UTC (rev 19012)
+++ search/trunk/hibernate-search/src/main/java/org/hibernate/search/SearchFactory.java	2010-03-17 16:30:48 UTC (rev 19013)
@@ -25,6 +25,8 @@
 package org.hibernate.search;
 
 import org.apache.lucene.analysis.Analyzer;
+
+import org.hibernate.search.query.dsl.v2.QueryContextBuilder;
 import org.hibernate.search.reader.ReaderProvider;
 import org.hibernate.search.store.DirectoryProvider;
 
@@ -75,4 +77,9 @@
 	 * class is not an indexed entity.
 	 */
 	Analyzer getAnalyzer(Class<?> clazz);
+
+	/**
+	 * Return a query builder providing a fluent API to create Lucene queries
+	 */
+	QueryContextBuilder buildQueryBuilder();
 }

Modified: search/trunk/hibernate-search/src/main/java/org/hibernate/search/impl/SearchFactoryImpl.java
===================================================================
--- search/trunk/hibernate-search/src/main/java/org/hibernate/search/impl/SearchFactoryImpl.java	2010-03-16 22:15:51 UTC (rev 19012)
+++ search/trunk/hibernate-search/src/main/java/org/hibernate/search/impl/SearchFactoryImpl.java	2010-03-17 16:30:48 UTC (rev 19013)
@@ -78,6 +78,8 @@
 import org.hibernate.search.filter.FilterCachingStrategy;
 import org.hibernate.search.filter.MRUFilterCachingStrategy;
 import org.hibernate.search.filter.ShardSensitiveOnlyFilter;
+import org.hibernate.search.query.dsl.v2.QueryContextBuilder;
+import org.hibernate.search.query.dsl.v2.impl.ConnectedQueryContextBuilder;
 import org.hibernate.search.reader.ReaderProvider;
 import org.hibernate.search.reader.ReaderProviderFactory;
 import org.hibernate.search.store.DirectoryProvider;
@@ -476,6 +478,10 @@
 		return builder.getAnalyzer();
 	}
 
+	public QueryContextBuilder buildQueryBuilder() {
+		return new ConnectedQueryContextBuilder( this );
+	}
+
 	private void initDocumentBuilders(SearchConfiguration cfg, ReflectionManager reflectionManager) {
 		InitContext context = new InitContext( cfg );
 		Iterator<Class<?>> iter = cfg.getClassMappings();

Modified: search/trunk/hibernate-search/src/main/java/org/hibernate/search/query/dsl/v2/QueryBuilder.java
===================================================================
--- search/trunk/hibernate-search/src/main/java/org/hibernate/search/query/dsl/v2/QueryBuilder.java	2010-03-16 22:15:51 UTC (rev 19012)
+++ search/trunk/hibernate-search/src/main/java/org/hibernate/search/query/dsl/v2/QueryBuilder.java	2010-03-17 16:30:48 UTC (rev 19013)
@@ -1,7 +1,5 @@
 package org.hibernate.search.query.dsl.v2;
 
-import org.hibernate.search.query.dsl.v2.TermContext;
-
 /**
  * @author Emmanuel Bernard
  */

Modified: search/trunk/hibernate-search/src/main/java/org/hibernate/search/query/dsl/v2/QueryContextBuilder.java
===================================================================
--- search/trunk/hibernate-search/src/main/java/org/hibernate/search/query/dsl/v2/QueryContextBuilder.java	2010-03-16 22:15:51 UTC (rev 19012)
+++ search/trunk/hibernate-search/src/main/java/org/hibernate/search/query/dsl/v2/QueryContextBuilder.java	2010-03-17 16:30:48 UTC (rev 19013)
@@ -1,8 +1,20 @@
 package org.hibernate.search.query.dsl.v2;
 
-import org.apache.lucene.analysis.Analyzer;
-
 /**
+ * Query builder that needs contextualization:
+ * A query builder should know which entity or analyzer it relies on.
+ *
+ * <code>
+ * QueryBuilder builder =
+ * searchFactory.buildQueryBuilder()
+ *   .forEntity(Customer.class)
+ *     .overridesForField("profession", "acronym-analyzer")
+ *     .get();
+ * </code>
+ *
+ * overridesForField is optional (and usually not needed). This method overrides the
+ * underlying analyzer (for a given field) used to build queries.
+ *
  * @author Emmanuel Bernard
  */
 public interface QueryContextBuilder {
@@ -10,6 +22,10 @@
 	EntityContext forEntity(Class<?> entityType);
 	interface EntityContext {
 		EntityContext overridesForField(String field, String analyzerName);
+
+		/**
+		 * return the query builder
+		 */
 		QueryBuilder get();
 	}
 }

Modified: search/trunk/hibernate-search/src/main/java/org/hibernate/search/query/dsl/v2/TermContext.java
===================================================================
--- search/trunk/hibernate-search/src/main/java/org/hibernate/search/query/dsl/v2/TermContext.java	2010-03-16 22:15:51 UTC (rev 19012)
+++ search/trunk/hibernate-search/src/main/java/org/hibernate/search/query/dsl/v2/TermContext.java	2010-03-17 16:30:48 UTC (rev 19013)
@@ -2,8 +2,6 @@
 
 import org.apache.lucene.search.Query;
 
-import org.hibernate.search.query.dsl.v2.QueryBuilder;
-
 /**
  * @author Emmanuel Bernard
  */

Modified: search/trunk/hibernate-search/src/main/java/org/hibernate/search/query/dsl/v2/impl/ConnectedTermContext.java
===================================================================
--- search/trunk/hibernate-search/src/main/java/org/hibernate/search/query/dsl/v2/impl/ConnectedTermContext.java	2010-03-16 22:15:51 UTC (rev 19012)
+++ search/trunk/hibernate-search/src/main/java/org/hibernate/search/query/dsl/v2/impl/ConnectedTermContext.java	2010-03-17 16:30:48 UTC (rev 19013)
@@ -106,14 +106,21 @@
 				catch ( IOException e ) {
 					throw new AssertionFailure("IO exception while reading String stream??", e);
 				}
-
-				BooleanQuery finalQuery = new BooleanQuery();
-				for (String term : terms) {
-					Query termQuery = createTermQuery(term);
-					//termQuery.setBoost( boost );
-					finalQuery.add( termQuery, BooleanClause.Occur.SHOULD );
+				if ( terms.size() == 0 ) {
+					throw new SearchException("try to search with an empty string: " + field);
 				}
-				return finalQuery;
+				else if (terms.size() == 1 ) {
+					return createTermQuery( terms.get( 0 ) );
+				}
+				else {
+					BooleanQuery finalQuery = new BooleanQuery();
+					for (String term : terms) {
+						Query termQuery = createTermQuery(term);
+						//termQuery.setBoost( boost );
+						finalQuery.add( termQuery, BooleanClause.Occur.SHOULD );
+					}
+					return finalQuery;
+				}
 			}
 		}
 

Added: search/trunk/hibernate-search/src/test/java/org/hibernate/search/test/query/dsl/DSLTest.java
===================================================================
--- search/trunk/hibernate-search/src/test/java/org/hibernate/search/test/query/dsl/DSLTest.java	                        (rev 0)
+++ search/trunk/hibernate-search/src/test/java/org/hibernate/search/test/query/dsl/DSLTest.java	2010-03-17 16:30:48 UTC (rev 19013)
@@ -0,0 +1,157 @@
+package org.hibernate.search.test.query.dsl;
+
+import java.util.List;
+
+import org.apache.lucene.search.Query;
+import org.apache.solr.analysis.LowerCaseFilterFactory;
+import org.apache.solr.analysis.NGramFilterFactory;
+import org.apache.solr.analysis.SnowballPorterFilterFactory;
+import org.apache.solr.analysis.StandardFilterFactory;
+import org.apache.solr.analysis.StandardTokenizerFactory;
+import org.apache.solr.analysis.StopFilterFactory;
+
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.search.Environment;
+import org.hibernate.search.FullTextSession;
+import org.hibernate.search.Search;
+import org.hibernate.search.annotations.Factory;
+import org.hibernate.search.cfg.SearchMapping;
+import org.hibernate.search.query.dsl.v2.QueryBuilder;
+import org.hibernate.search.test.SearchTestCase;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class DSLTest extends SearchTestCase {
+
+	public void testTermQueryOnAnalyzer() throws Exception {
+		Session session = openSession();
+		FullTextSession fts = Search.getFullTextSession( session );
+		Transaction transaction = fts.beginTransaction();
+		fts.persist( new Month("January", "Month of colder and whitening") );
+		fts.persist( new Month("February", "Month of snowboarding") );
+		transaction.commit();
+
+		fts.clear();
+
+		transaction = fts.beginTransaction();
+		final QueryBuilder monthQb = fts.getSearchFactory()
+				.buildQueryBuilder().forEntity( Month.class ).get();
+		Query 
+		//regular term query
+		query = monthQb.term().on( "mythology" ).matches( "cold" ).createQuery();
+
+		assertEquals( 0, fts.createFullTextQuery( query, Month.class ).getResultSize() );
+
+		//term query based on several words
+		query = monthQb.term().on( "mythology" ).matches( "colder darker" ).createQuery();
+
+		assertEquals( 1, fts.createFullTextQuery( query, Month.class ).getResultSize() );
+
+		//term query applying the analyzer and generating one term per word
+		query = monthQb.term().on( "mythology_stem" ).matches( "snowboard" ).createQuery();
+
+		assertEquals( 1, fts.createFullTextQuery( query, Month.class ).getResultSize() );
+
+		//term query applying the analyzer and generating several terms per word
+		query = monthQb.term().on( "mythology_ngram" ).matches( "snobored" ).createQuery();
+
+		assertEquals( 1, fts.createFullTextQuery( query, Month.class ).getResultSize() );
+
+		//term query not using analyzers
+		query = monthQb.term().on( "mythology" ).matches( "Month" ).ignoreAnalyzer().createQuery();
+
+		assertEquals( 0, fts.createFullTextQuery( query, Month.class ).getResultSize() );
+
+		query = monthQb.term().on( "mythology" ).matches( "Month" ).createQuery();
+
+		final List<Month> results = fts.createFullTextQuery( query, Month.class ).list();
+		assertEquals( 2, results.size() );
+
+		for (Month entity : results) {
+			fts.delete( entity );
+		}
+		transaction.commit();
+		fts.close();
+	}
+
+	public void tesFuzzyAndWildcardQuery() throws Exception {
+		Session session = openSession();
+		FullTextSession fts = Search.getFullTextSession( session );
+		Transaction transaction = fts.beginTransaction();
+		fts.persist( new Month("January", "Month of colder and whitening") );
+		fts.persist( new Month("February", "Month of snowboarding") );
+		transaction.commit();
+
+		fts.clear();
+
+		transaction = fts.beginTransaction();
+		final QueryBuilder monthQb = fts.getSearchFactory()
+				.buildQueryBuilder().forEntity( Month.class ).get();
+		Query
+		//fuzzy search with custom threshold and prefix
+		query = monthQb
+				.term().on( "mythology" ).matches( "calder" )
+					.fuzzy()
+						.threshold( .8f )
+						.prefixLength( 1 )
+				.createQuery();
+
+		assertEquals( 1, fts.createFullTextQuery( query, Month.class ).getResultSize() );
+
+		//wildcard query
+		query = monthQb
+				.term().on( "mythology" ).matches( "mon*" )
+					.wildcard()
+				.createQuery();
+
+		assertEquals( 2, fts.createFullTextQuery( query, Month.class ).getResultSize() );
+
+		final List<Month> results = fts.createFullTextQuery( query, Month.class ).list();
+		assertEquals( 2, results.size() );
+
+		for (Month entity : results) {
+			fts.delete( entity );
+		}
+		transaction.commit();
+		fts.close();
+	}
+
+
+	@Override
+	protected Class<?>[] getMappings() {
+		return new Class<?>[] {
+				Month.class
+		};
+	}
+
+	@Override
+	protected void configure(Configuration cfg) {
+		super.configure( cfg );
+		cfg.getProperties().put( Environment.MODEL_MAPPING, MappingFactory.class.getName() );
+	}
+
+	public static class MappingFactory {
+		@Factory
+			public SearchMapping build() {
+				SearchMapping mapping = new SearchMapping();
+			mapping
+				.analyzerDef( "stemmer", StandardTokenizerFactory.class )
+					.filter( StandardFilterFactory.class )
+					.filter( LowerCaseFilterFactory.class )
+					.filter( StopFilterFactory.class )
+					.filter( SnowballPorterFilterFactory.class )
+						.param( "language", "English" )
+				.analyzerDef( "ngram", StandardTokenizerFactory.class )
+					.filter( StandardFilterFactory.class )
+					.filter( LowerCaseFilterFactory.class )
+					.filter( StopFilterFactory.class )
+					.filter( NGramFilterFactory.class )
+						.param( "minGramSize", "3" )
+						.param( "maxGramSize", "3" );
+			return mapping;
+		}
+	}
+}

Added: search/trunk/hibernate-search/src/test/java/org/hibernate/search/test/query/dsl/Month.java
===================================================================
--- search/trunk/hibernate-search/src/test/java/org/hibernate/search/test/query/dsl/Month.java	                        (rev 0)
+++ search/trunk/hibernate-search/src/test/java/org/hibernate/search/test/query/dsl/Month.java	2010-03-17 16:30:48 UTC (rev 19013)
@@ -0,0 +1,44 @@
+package org.hibernate.search.test.query.dsl;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+import org.hibernate.search.annotations.Analyzer;
+import org.hibernate.search.annotations.Field;
+import org.hibernate.search.annotations.Fields;
+import org.hibernate.search.annotations.Indexed;
+
+/**
+ * @author Emmanuel Bernard
+ */
+ at Entity
+ at Indexed
+public class Month {
+	public Month() {}
+	
+	public Month(String name, String mythology) {
+		this.name = name;
+		this.mythology = mythology;
+	}
+
+	@Id @GeneratedValue
+	public Integer getId() { return id; }
+	public void setId(Integer id) { this.id = id; }
+	private Integer id;
+
+	@Field
+	public String getName() { return name; }
+	public void setName(String name) { this.name = name; }
+	private String name;
+
+	@Fields( {
+			@Field,
+			@Field(name="mythology_stem", analyzer = @Analyzer(definition = "stemmer") ),
+			@Field(name="mythology_ngram", analyzer = @Analyzer(definition = "ngram") )
+	})
+	public String getMythology() { return mythology; }
+	public void setMythology(String mythology) { this.mythology = mythology; }
+	private String mythology;
+}
+



More information about the hibernate-commits mailing list