diff --git a/README.md b/README.md index 9c9ee74..93a510c 100644 --- a/README.md +++ b/README.md @@ -114,30 +114,30 @@ class MyDomainClass { @DocumentId Long id - @Field(index=Index.TOKENIZED) + @Field(index=Index.YES) String author - @Field(index=Index.TOKENIZED) + @Field(index=Index.YES) String body @Field @DateBridge(resolution=Resolution.DAY) Date publishedDate - @Field(index=Index.TOKENIZED) + @Field(index=Index.YES) String summary - @Field(index=Index.TOKENIZED) + @Field(index=Index.YES) String title - @Field(index=Index.UN_TOKENIZED) + @Field(index=Index.YES) Status status @Field @NumericField( precisionStep = 2) Double price - @Field(index=Index.UN_TOKENIZED) + @Field(index=Index.YES) @FieldBridge(impl = PaddedIntegerBridge.class, params = @Parameter(name="padding", value="10")) Integer someInteger @@ -453,8 +453,8 @@ class MyDomainClass { [...] static search = { - author index: 'tokenized', store: 'yes' - body index: 'tokenized', store: 'yes' + author index: 'yes', store: 'yes' + body index: 'yes', store: 'yes' } } ``` @@ -515,8 +515,8 @@ class MyDomainClass { static search = { analyzer = 'ngram' - author index: 'tokenized' - body index: 'tokenized' + author index: 'yes' + body index: 'yes' } } @@ -532,8 +532,9 @@ class MyDomainClass { ... static search = { - author index: 'tokenized' - body index: 'tokenized', analyzer: 'ngram' + author index: 'yes' + body index: 'yes', analyzer: 'ngram' + other index: 'yes', analyzer: new MyFilter() } } diff --git a/build.gradle b/build.gradle index a19e506..c21d531 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,7 @@ buildscript { } } -version "2.0" +version "2.0.1" group "org.grails.plugins" apply plugin:"eclipse" diff --git a/src/main/groovy/grails/plugins/hibernate/search/HibernateSearchCapableSessionFactoryBean.java b/src/main/groovy/grails/plugins/hibernate/search/HibernateSearchCapableSessionFactoryBean.java index a19d711..7674895 100644 --- a/src/main/groovy/grails/plugins/hibernate/search/HibernateSearchCapableSessionFactoryBean.java +++ b/src/main/groovy/grails/plugins/hibernate/search/HibernateSearchCapableSessionFactoryBean.java @@ -187,9 +187,8 @@ protected SessionFactory doBuildSessionFactory() { .getStaticPropertyValue("search", Closure.class); if (searchClosure != null) { - SearchMappingEntityConfig searchMappingEntityConfig = new SearchMappingEntityConfig(searchMapping, - domainClass.getClazz()); + domainClass); searchClosure.setDelegate(searchMappingEntityConfig); searchClosure.setResolveStrategy(Closure.DELEGATE_FIRST); diff --git a/src/main/groovy/grails/plugins/hibernate/search/SearchMappingEntityConfig.groovy b/src/main/groovy/grails/plugins/hibernate/search/SearchMappingEntityConfig.groovy index 5bea45e..0942521 100644 --- a/src/main/groovy/grails/plugins/hibernate/search/SearchMappingEntityConfig.groovy +++ b/src/main/groovy/grails/plugins/hibernate/search/SearchMappingEntityConfig.groovy @@ -22,12 +22,17 @@ import org.hibernate.search.annotations.Store import org.hibernate.search.annotations.TermVector import org.hibernate.search.cfg.DocumentIdMapping; import org.hibernate.search.cfg.EntityMapping +import org.hibernate.search.cfg.FieldMapping; +import org.hibernate.search.cfg.PropertyMapping; import org.hibernate.search.cfg.SearchMapping import org.slf4j.Logger import org.slf4j.LoggerFactory; import java.lang.annotation.ElementType +import java.lang.reflect.Field; +import grails.core.GrailsDomainClass +import grails.core.GrailsDomainClassProperty; import grails.plugins.*; class SearchMappingEntityConfig { @@ -39,14 +44,16 @@ class SearchMappingEntityConfig { def analyzer def searchMapping - private final clazz + private final GrailsDomainClass domainClass private final EntityMapping entityMapping - public SearchMappingEntityConfig( SearchMapping searchMapping, Class clazz ) { - this.clazz = clazz - this.entityMapping = searchMapping.entity( clazz ) + public SearchMappingEntityConfig( SearchMapping searchMapping, GrailsDomainClass domainClass ) { + this.domainClass = domainClass + + this.entityMapping = searchMapping.entity( domainClass.getClazz() ) this.searchMapping = entityMapping.indexed().property( IDENTITY, ElementType.FIELD ).documentId() + } def setClassBridge( Map classBridge ) { @@ -60,9 +67,11 @@ class SearchMappingEntityConfig { def invokeMethod( String name, argsAsList ) { def args = argsAsList[0] ?: [:] - + if ( args.indexEmbedded ) { + log.debug "adding indexEmbedded property: " + name + searchMapping = searchMapping.property( name, ElementType.FIELD ).indexEmbedded() if ( args.indexEmbedded instanceof Map ) { @@ -78,64 +87,91 @@ class SearchMappingEntityConfig { } } else if ( args.containedIn ) { + log.debug "adding containedIn property: " + name + searchMapping = searchMapping.property( name, ElementType.FIELD ).containedIn() } else { - - log.debug "adding indexed field: " + name - searchMapping = searchMapping.property( name, ElementType.FIELD ).field().name( args.name ?: name ) + log.debug "adding indexed property: " + name - if ( args.containsKey('analyze') ) { - searchMapping = searchMapping.analyze( args.analyze ? Analyze.YES : Analyze.NO ) - } + GrailsDomainClassProperty property = domainClass.getPersistentProperty(name); + + EntityMapping targetEntityMapping = entityMapping; - if ( analyzer ) { - searchMapping = searchMapping.analyzer( analyzer ) - } + // find the field in the parent class hierarchy (starting from domain class itself) + Class currentDomainClass = domainClass.getClazz(); + while (currentDomainClass != null) { + try { + Field backingField = currentDomainClass.getDeclaredField(property.getName()); + + // field exists on domain class hierarchy + targetEntityMapping = searchMapping.entity( currentDomainClass ); + log.debug "> property " + backingField.getDeclaringClass() + ".$name found"; + currentDomainClass = null; + } catch (NoSuchFieldException e) { + currentDomainClass = currentDomainClass.getSuperclass(); + } + } - if ( args.analyzer ) { - searchMapping = searchMapping.analyzer( args.analyzer ) - } + FieldMapping fieldMapping = targetEntityMapping.property( name, ElementType.FIELD ).field().name( args.name ?: name ) + registerIndexedProperty(fieldMapping, args) + } + } + + private void registerIndexedProperty(FieldMapping fieldMapping, args) { + + def searchMapping = fieldMapping; + + if ( args.containsKey('analyze') ) { + searchMapping = searchMapping.analyze( args.analyze ? Analyze.YES : Analyze.NO ) + } + + if ( analyzer ) { + searchMapping = searchMapping.analyzer( analyzer ) + } - if ( args.index ) { - searchMapping = searchMapping.index( Index."${args.index.toUpperCase()}" ) - } + if ( args.analyzer ) { + searchMapping = searchMapping.analyzer( args.analyzer ) + } - if ( args.store ) { - searchMapping = searchMapping.store( Store."${args.store.toUpperCase()}" ) - } + if ( args.index ) { + searchMapping = searchMapping.index( Index."${args.index.toUpperCase()}" ) + } - if ( args.termVector ) { - searchMapping = searchMapping.termVector( TermVector."${args.termVector.toUpperCase()}" ) - } + if ( args.store ) { + searchMapping = searchMapping.store( Store."${args.store.toUpperCase()}" ) + } - if ( args.norms ) { - searchMapping = searchMapping.norms( Norms."${args.norms.toUpperCase()}" ) - } + if ( args.termVector ) { + searchMapping = searchMapping.termVector( TermVector."${args.termVector.toUpperCase()}" ) + } - if ( args.numeric ) { - searchMapping = searchMapping.numericField().precisionStep( args.numeric ) - } + if ( args.norms ) { + searchMapping = searchMapping.norms( Norms."${args.norms.toUpperCase()}" ) + } - if ( args.date ) { - searchMapping = searchMapping.dateBridge( Resolution."${args.date.toUpperCase()}" ) - } + if ( args.numeric ) { + searchMapping = searchMapping.numericField().precisionStep( args.numeric ) + } - if ( args.boost ) { - searchMapping = searchMapping.boost( args.boost ) - } + if ( args.date ) { + searchMapping = searchMapping.dateBridge( Resolution."${args.date.toUpperCase()}" ) + } - if ( args.bridge ) { + if ( args.boost ) { + searchMapping = searchMapping.boost( args.boost ) + } - searchMapping = searchMapping.bridge( args.bridge["class"] ) + if ( args.bridge ) { - def params = args.bridge["params"] + searchMapping = searchMapping.bridge( args.bridge["class"] ) - params?.each {k, v -> - searchMapping = searchMapping.param( k.toString(), v.toString() ) - } - } - } - } + def params = args.bridge["params"] + + params?.each {k, v -> + searchMapping = searchMapping.param( k.toString(), v.toString() ) + } + } + } }