[hibernate-commits] Hibernate SVN: r16269 - in search/trunk/src: main/java/org/hibernate/search/cfg and 2 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Tue Apr 7 12:31:07 EDT 2009


Author: epbernard
Date: 2009-04-07 12:31:07 -0400 (Tue, 07 Apr 2009)
New Revision: 16269

Added:
   search/trunk/src/main/java/org/hibernate/search/cfg/ConcatStringBridge.java
   search/trunk/src/main/java/org/hibernate/search/cfg/FieldBridgeMapping.java
Modified:
   search/trunk/src/main/java/org/hibernate/search/annotations/Field.java
   search/trunk/src/main/java/org/hibernate/search/annotations/FieldBridge.java
   search/trunk/src/main/java/org/hibernate/search/cfg/FieldMapping.java
   search/trunk/src/main/java/org/hibernate/search/impl/MappingModelMetadataProvider.java
   search/trunk/src/test/java/org/hibernate/search/test/configuration/ProgrammaticMappingTest.java
Log:
HSEARCH-352 boost and field bridge support on field()

Modified: search/trunk/src/main/java/org/hibernate/search/annotations/Field.java
===================================================================
--- search/trunk/src/main/java/org/hibernate/search/annotations/Field.java	2009-04-06 21:43:00 UTC (rev 16268)
+++ search/trunk/src/main/java/org/hibernate/search/annotations/Field.java	2009-04-07 16:31:07 UTC (rev 16269)
@@ -51,7 +51,7 @@
 
 
 	/**
-	 * Field bridge used. Default is autowired.
+	 * Boost factor, default 1
 	 */
 	Boost boost() default @Boost( value = 1.0F );
 

Modified: search/trunk/src/main/java/org/hibernate/search/annotations/FieldBridge.java
===================================================================
--- search/trunk/src/main/java/org/hibernate/search/annotations/FieldBridge.java	2009-04-06 21:43:00 UTC (rev 16268)
+++ search/trunk/src/main/java/org/hibernate/search/annotations/FieldBridge.java	2009-04-07 16:31:07 UTC (rev 16269)
@@ -17,7 +17,7 @@
 @Documented
 public @interface FieldBridge {
 	//default to embed @FieldBridge in @Field
-	public Class impl() default void.class;
+	public Class<?> impl() default void.class;
 
 	public Parameter[] params() default {};
 }

Added: search/trunk/src/main/java/org/hibernate/search/cfg/ConcatStringBridge.java
===================================================================
--- search/trunk/src/main/java/org/hibernate/search/cfg/ConcatStringBridge.java	                        (rev 0)
+++ search/trunk/src/main/java/org/hibernate/search/cfg/ConcatStringBridge.java	2009-04-07 16:31:07 UTC (rev 16269)
@@ -0,0 +1,28 @@
+package org.hibernate.search.cfg;
+
+import java.util.Map;
+
+import org.hibernate.search.bridge.ParameterizedBridge;
+import org.hibernate.search.bridge.StringBridge;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class ConcatStringBridge implements StringBridge, ParameterizedBridge{
+	public static final String SIZE = "size";
+	private int size;
+
+	public String objectToString(Object object) {
+		if (object == null) return "";
+		if ( ! (object instanceof String) ) {
+			throw new RuntimeException( "not a string" );
+		}
+		String string = object.toString();
+		int maxSize = string.length() >= size ? size : string.length();
+		return string.substring( 0, maxSize );
+	}
+
+	public void setParameterValues(Map parameters) {
+		size =  Integer.valueOf( (String) parameters.get( SIZE ) );
+	}
+}

Added: search/trunk/src/main/java/org/hibernate/search/cfg/FieldBridgeMapping.java
===================================================================
--- search/trunk/src/main/java/org/hibernate/search/cfg/FieldBridgeMapping.java	                        (rev 0)
+++ search/trunk/src/main/java/org/hibernate/search/cfg/FieldBridgeMapping.java	2009-04-07 16:31:07 UTC (rev 16269)
@@ -0,0 +1,94 @@
+package org.hibernate.search.cfg;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.lang.annotation.ElementType;
+
+import org.apache.solr.analysis.TokenizerFactory;
+
+import org.hibernate.search.annotations.Store;
+import org.hibernate.search.annotations.Index;
+import org.hibernate.search.annotations.TermVector;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class FieldBridgeMapping {
+	private final SearchMapping mapping;
+	private final EntityDescriptor entity;
+	private final PropertyDescriptor property;
+	private final FieldMapping fieldMapping;
+	private final Map<String, Object> bridge = new HashMap<String, Object>();;
+
+	public FieldBridgeMapping(Class<?> impl, Map<String, Object> field,
+							  FieldMapping fieldMapping,
+							  PropertyDescriptor property,
+							  EntityDescriptor entity,
+							  SearchMapping mapping) {
+		this.mapping = mapping;
+		this.entity = entity;
+		this.property = property;
+		this.fieldMapping = fieldMapping;
+		bridge.put( "impl", impl );
+		field.put( "bridge", bridge );
+	}
+
+	public FieldBridgeMapping param(String name, String value) {
+		Map<String, Object> param = SearchMapping.addElementToAnnotationArray(bridge, "params");
+		param.put("name", name);
+		param.put("value", value);
+		return this;
+	}
+
+	//FieldMapping level
+	public FieldMapping name(String fieldName) {
+		return fieldMapping.name( fieldName );
+	}
+
+	public FieldMapping store(Store store) {
+		return fieldMapping.store( store );
+	}
+
+	public FieldMapping index(Index index) {
+		return fieldMapping.index( index );
+	}
+
+	public FieldMapping termVector(TermVector termVector) {
+		return fieldMapping.termVector( termVector );
+	}
+
+	public FieldMapping boost(float boost) {
+		return fieldMapping.boost( boost );
+	}
+
+	public FieldMapping analyzer(Class<?> analyzerClass) {
+		return fieldMapping.analyzer( analyzerClass );
+	}
+
+	public FieldMapping analyzer(String analyzerDef) {
+		return fieldMapping.analyzer( analyzerDef );
+	}
+
+	//PropertyMapping level
+	public FieldMapping field() {
+		return new FieldMapping(property, entity, mapping);
+	}
+
+	//EntityMapping level
+	public PropertyMapping property(String name, ElementType type) {
+		return new PropertyMapping(name, type, entity, mapping);
+	}
+
+	//Global level
+	public AnalyzerDefMapping analyzerDef(String name, Class<? extends TokenizerFactory> tokenizerFactory) {
+		return new AnalyzerDefMapping(name, tokenizerFactory, mapping);
+	}
+
+	public EntityMapping indexedClass(Class<?> entityType) {
+		return new EntityMapping(entityType, null, mapping);
+	}
+
+	public EntityMapping indexedClass(Class<?> entityType, String indexName) {
+		return new EntityMapping(entityType, indexName,  mapping);
+	}
+}

Modified: search/trunk/src/main/java/org/hibernate/search/cfg/FieldMapping.java
===================================================================
--- search/trunk/src/main/java/org/hibernate/search/cfg/FieldMapping.java	2009-04-06 21:43:00 UTC (rev 16268)
+++ search/trunk/src/main/java/org/hibernate/search/cfg/FieldMapping.java	2009-04-07 16:31:07 UTC (rev 16269)
@@ -8,20 +8,20 @@
 
 import org.hibernate.search.annotations.Index;
 import org.hibernate.search.annotations.Store;
+import org.hibernate.search.annotations.TermVector;
 
 /**
  * @author Emmanuel Bernard
  */
 public class FieldMapping {
-	private SearchMapping mapping;
-	private EntityDescriptor entity;
-	private PropertyDescriptor property;
-	private Map<String, Object> field = new HashMap<String, Object>();
+	private final SearchMapping mapping;
+	private final EntityDescriptor entity;
+	private final PropertyDescriptor property;
+	private final Map<String, Object> field = new HashMap<String, Object>();
 
 	public FieldMapping(PropertyDescriptor property, EntityDescriptor entity, SearchMapping mapping) {
 		this.mapping = mapping;
 		this.entity = entity;
-		this.mapping = mapping;
 		this.property = property;
 		property.addField(field);
 	}
@@ -41,6 +41,22 @@
 		return this;
 	}
 
+	public FieldMapping termVector(TermVector termVector) {
+		field.put( "termVector", termVector );
+		return this;
+	}
+
+	public FieldMapping boost(float boost) {
+		final Map<String, Object> boostAnn = new HashMap<String, Object>();
+		boostAnn.put( "value", boost );
+		field.put( "boost", boostAnn );
+		return this;
+	}
+
+	public FieldBridgeMapping bridge(Class<?> impl) {
+		return new FieldBridgeMapping( impl, field, this, property, entity, mapping );
+	}
+
 	public FieldMapping analyzer(Class<?> analyzerClass) {
 		final Map<String, Object> analyzer = new HashMap<String, Object>();
 		analyzer.put( "impl", analyzerClass );

Modified: search/trunk/src/main/java/org/hibernate/search/impl/MappingModelMetadataProvider.java
===================================================================
--- search/trunk/src/main/java/org/hibernate/search/impl/MappingModelMetadataProvider.java	2009-04-06 21:43:00 UTC (rev 16268)
+++ search/trunk/src/main/java/org/hibernate/search/impl/MappingModelMetadataProvider.java	2009-04-07 16:31:07 UTC (rev 16269)
@@ -2,7 +2,6 @@
 
 import java.util.Map;
 import java.util.List;
-import java.util.Set;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Collection;
@@ -31,6 +30,8 @@
 import org.hibernate.search.annotations.Parameter;
 import org.hibernate.search.annotations.TokenFilterDef;
 import org.hibernate.search.annotations.AnalyzerDefs;
+import org.hibernate.search.annotations.Boost;
+import org.hibernate.search.annotations.FieldBridge;
 
 /**
  * @author Emmanuel Bernard
@@ -96,8 +97,7 @@
 				Map<String, Object> tokenizer = (Map<String, Object>) entry.getValue();
 				for( Map.Entry<String, Object> tokenizerEntry : tokenizer.entrySet() ) {
 					if ( tokenizerEntry.getKey().equals( "params" ) ) {
-						Parameter[] paramsArray = createParams( (List<Map<String, Object>>) tokenizerEntry.getValue() );
-						tokenizerAnnotation.setValue( "params", paramsArray );
+						addParamsToAnnotation( tokenizerAnnotation, tokenizerEntry );
 					}
 					else {
 						tokenizerAnnotation.setValue( tokenizerEntry.getKey(), tokenizerEntry.getValue() );
@@ -116,6 +116,11 @@
 		return AnnotationFactory.create( analyzerDefAnnotation );
 	}
 
+	static private void addParamsToAnnotation(AnnotationDescriptor annotationDescriptor, Map.Entry<String, Object> entry) {
+		Parameter[] paramsArray = createParams( ( List<Map<String, Object>> ) entry.getValue() );
+		annotationDescriptor.setValue( "params", paramsArray );
+	}
+
 	private TokenFilterDef[] createFilters(List<Map<String, Object>> filters) {
 		TokenFilterDef[] filtersArray = new TokenFilterDef[filters.size()];
 		int index = 0;
@@ -123,8 +128,7 @@
 			AnnotationDescriptor filterAnn = new AnnotationDescriptor( TokenFilterDef.class );
 			for ( Map.Entry<String, Object> filterEntry : filter.entrySet() ) {
 				if ( filterEntry.getKey().equals( "params" ) ) {
-					Parameter[] paramsArray = createParams( (List<Map<String, Object>>) filterEntry.getValue() );
-					filterAnn.setValue( "params", paramsArray );
+					addParamsToAnnotation( filterAnn, filterEntry );
 				}
 				else {
 					filterAnn.setValue( filterEntry.getKey(), filterEntry.getValue() );
@@ -136,7 +140,7 @@
 		return filtersArray;
 	}
 
-	private Parameter[] createParams(List<Map<String, Object>> params) {
+	private static Parameter[] createParams(List<Map<String, Object>> params) {
 		Parameter[] paramArray = new Parameter[ params.size() ];
 		int index = 0;
 		for ( Map<String, Object> entry : params) {
@@ -249,6 +253,29 @@
 						}
 						fieldAnnotation.setValue( "analyzer", AnnotationFactory.create( analyzerAnnotation ) );
 					}
+					else if ( entry.getKey().equals( "boost" ) ) {
+						AnnotationDescriptor boostAnnotation = new AnnotationDescriptor( Boost.class );
+						@SuppressWarnings( "unchecked" )
+						Map<String, Object> boost = (Map<String, Object>) entry.getValue();
+						for( Map.Entry<String, Object> boostEntry : boost.entrySet() ) {
+							boostAnnotation.setValue( boostEntry.getKey(), boostEntry.getValue() );
+						}
+						fieldAnnotation.setValue( "boost", AnnotationFactory.create( boostAnnotation ) );
+					}
+					else if ( entry.getKey().equals( "bridge" ) ) {
+						AnnotationDescriptor bridgeAnnotation = new AnnotationDescriptor( FieldBridge.class );
+						@SuppressWarnings( "unchecked" )
+						Map<String, Object> bridge = (Map<String, Object>) entry.getValue();
+						for( Map.Entry<String, Object> bridgeEntry : bridge.entrySet() ) {
+							if ( bridgeEntry.getKey().equals( "params" ) ) {
+								addParamsToAnnotation( bridgeAnnotation, bridgeEntry );
+							}
+							else {
+								bridgeAnnotation.setValue( bridgeEntry.getKey(), bridgeEntry.getValue() );
+							}
+						}
+						fieldAnnotation.setValue( "bridge", AnnotationFactory.create( bridgeAnnotation ) );
+					}
 					else {
 						fieldAnnotation.setValue( entry.getKey(), entry.getValue() );
 					}

Modified: search/trunk/src/test/java/org/hibernate/search/test/configuration/ProgrammaticMappingTest.java
===================================================================
--- search/trunk/src/test/java/org/hibernate/search/test/configuration/ProgrammaticMappingTest.java	2009-04-06 21:43:00 UTC (rev 16268)
+++ search/trunk/src/test/java/org/hibernate/search/test/configuration/ProgrammaticMappingTest.java	2009-04-07 16:31:07 UTC (rev 16269)
@@ -1,6 +1,7 @@
 package org.hibernate.search.test.configuration;
 
 import java.lang.annotation.ElementType;
+import java.util.List;
 
 import org.apache.solr.analysis.StandardTokenizerFactory;
 import org.apache.solr.analysis.SnowballPorterFilterFactory;
@@ -11,6 +12,7 @@
 import org.apache.lucene.analysis.standard.StandardAnalyzer;
 
 import org.hibernate.search.cfg.SearchMapping;
+import org.hibernate.search.cfg.ConcatStringBridge;
 import org.hibernate.search.annotations.Store;
 import org.hibernate.search.annotations.Index;
 import org.hibernate.search.test.analyzer.inheritance.ISOLatin1Analyzer;
@@ -18,6 +20,7 @@
 import org.hibernate.search.FullTextSession;
 import org.hibernate.search.Search;
 import org.hibernate.search.FullTextQuery;
+import org.hibernate.search.bridge.builtin.StringBridge;
 import org.hibernate.search.store.RAMDirectoryProvider;
 import org.hibernate.search.store.FSDirectoryProvider;
 import org.hibernate.cfg.Configuration;
@@ -52,7 +55,6 @@
 		s.delete( firstResult[1] );
 		tx.commit();
 		s.close();
-
 	}
 
 	public void testAnalyzerDef() throws Exception{
@@ -71,7 +73,7 @@
 
 		QueryParser parser = new QueryParser( "id", new StandardAnalyzer( ) );
 		org.apache.lucene.search.Query luceneQuery =  parser.parse( "street1_ngram:pea" );
-		System.out.print( luceneQuery.toString() );
+
 		final FullTextQuery query = s.createFullTextQuery( luceneQuery );
 		assertEquals( "Analyzer inoperant", 1, query.getResultSize() );
 
@@ -81,6 +83,71 @@
 
 	}
 
+	public void testBridgeMapping() throws Exception{
+		Address address = new Address();
+		address.setStreet1( "Peachtree Rd NE" );
+		address.setStreet2( "JBoss" );
+
+		FullTextSession s = Search.getFullTextSession( openSession() );
+		Transaction tx = s.beginTransaction();
+		s.persist( address );
+		tx.commit();
+
+		s.clear();
+
+		tx = s.beginTransaction();
+
+		QueryParser parser = new QueryParser( "id", new StandardAnalyzer( ) );
+		org.apache.lucene.search.Query luceneQuery = parser.parse( "street1:peac" );
+		FullTextQuery query = s.createFullTextQuery( luceneQuery );
+		assertEquals( "PrefixQuery should not be on", 0, query.getResultSize() );
+
+		luceneQuery = parser.parse( "street1_abridged:peac" );
+		query = s.createFullTextQuery( luceneQuery );
+		assertEquals( "Bridge not used", 1, query.getResultSize() );
+
+		s.delete( query.list().get( 0 ) );
+		tx.commit();
+		s.close();
+	}
+
+	public void testBoost() throws Exception{
+		FullTextSession s = Search.getFullTextSession( openSession() );
+		Transaction tx = s.beginTransaction();
+
+		Address address = new Address();
+		address.setStreet1( "Peachtree Rd NE" );
+		address.setStreet2( "Peachtnot Rd NE" );
+		s.persist( address );
+
+		address = new Address();
+		address.setStreet1( "Peachtnot Rd NE" );
+		address.setStreet2( "Peachtree Rd NE" );
+		s.persist( address );
+
+		tx.commit();
+
+		s.clear();
+
+		tx = s.beginTransaction();
+
+		QueryParser parser = new QueryParser( "id", new StandardAnalyzer( ) );
+		org.apache.lucene.search.Query luceneQuery = parser.parse( "street1:peachtree OR idx_street2:peachtree" );
+		FullTextQuery query = s.createFullTextQuery( luceneQuery ).setProjection( FullTextQuery.THIS, FullTextQuery.SCORE );
+		assertEquals( "expecting two results", 2, query.getResultSize() );
+
+		@SuppressWarnings( "unchecked" )
+		List<Object[]> results = query.list();
+
+		assertTrue( "first result should be strictly higher", (Float) results.get( 0 )[1] > (Float) results.get( 1 )[1]*1.9f );
+		assertEquals( "Wrong result ordered", address.getStreet1(), ( (Address) results.get( 0 )[0] ).getStreet1() );
+		for( Object[] result : results ) {
+			s.delete( result[0] );
+		}
+		tx.commit();
+		s.close();
+	}
+
 	@Override
 	protected void configure(Configuration cfg) {
 		super.configure( cfg );
@@ -96,8 +163,11 @@
 					.property( "street1", ElementType.FIELD )
 						.field()
 						.field().name( "street1_ngram" ).analyzer( "ngram" )
+						.field()
+							.name( "street1_abridged" )
+							.bridge( ConcatStringBridge.class ).param( ConcatStringBridge.SIZE, "4" )
 					.property( "street2", ElementType.METHOD )
-						.field().name( "idx_street2" ).store( Store.YES );
+						.field().name( "idx_street2" ).store( Store.YES ).boost( 2 );
 		cfg.getProperties().put( "hibernate.search.mapping_model", mapping );
 	}
 




More information about the hibernate-commits mailing list