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 );
}