Search code examples
grailselasticsearchgrails-plugingrails-domain-classgrails-3.1

unmarshalling domain class error in elastic search Grails


I'm trying to use ElasticSearch 1.0.0.2 in Grails 3.1.6.

The domain class is:

class Post {

String content
Date dateCreated

static belongsTo = [user: User]

static hasMany = [tags: Tag]

static searchable = {
    tags component : true
    user component: true
}
}

I've injected ElasticSearchService in my SearchController and trying to obtain search results as:

try {
            def searchResult = elasticSearchService.search("${params.q}")
//            def searchResult = Post.search("${params.q}")
            println("search result: "+searchResult)
            return [searchResult: searchResult]
        }catch (e){
            println e.message
            return [searchError: true]
        }

But getting error like this:

 ERROR grails.plugins.elasticsearch.conversion.unmarshall.DomainClassUnmarshaller - Error unmarshalling property 'user' of Class Post with id 4
java.lang.IllegalStateException: Property Post.user is not mapped as [component], but broken search hit found.
    at sun.reflect.GeneratedConstructorAccessor116.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
    at org.springsource.loaded.ri.ReflectiveInterceptor.jlrConstructorNewInstance(ReflectiveInterceptor.java:1075)
    at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:83)
    at org.codehaus.groovy.reflection.CachedConstructor.doConstructorInvoke(CachedConstructor.java:77)
    at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrap.callConstructor(ConstructorSite.java:84)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:247)
    at grails.plugins.elasticsearch.conversion.unmarshall.DomainClassUnmarshaller.unmarshallProperty(DomainClassUnmarshaller.groovy:206)
    at sun.reflect.GeneratedMethodAccessor339.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1432)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:210)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:59)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:52)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:64)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:190)

Would someone please tell me what mistake i'm making. Thanks.


Solution

  • Had the same problem, used this piece from the elastisearch plugin documentation to change my component to references which fixed my problem:

    3.8.1. Searchable Reference The searchable-reference mapping mode is the default mode used for association, and requires the searchable class of the association to be root-mapped in order to have its own index. With this mode, the associated domains are not completely marshalled in the resulting JSON document: only the id and the type of the instances are kept. When the document is retrieved from the index, the plugin will automatically rebuild the association from the indices using the stored id.

    Example

    class MyDomain {
     // odom is an association with the OtherDomain class, set as a   reference
     OtherDomain odom
    
       static searchable = {
          odom reference:true
       }
     }
    
    // The OtherDomain definition, with default searchable
     class OtherDomain {
        static searchable = true
    
         String field1 = "val1"
         String field2 = "val2"
         String field3 = "val3"
         String field4 = "val4"
     }
    

    When indexing an instance of MyDomain, the resulting JSON documents will be sent to ElasticSearch:

    {
        "mydomain": {
            "_id":1,
            "odom": { "id":1 }
        }
    }
    
    {
        "otherdomain": {
            "_id":1,
            "field1":"val1",
            "field2":"val2",
            "field3":"val3",
            "field4":"val4"
        }
    }
    

    Here is the link to the documentation http://noamt.github.io/elasticsearch-grails-plugin/docs/index.html#searchableComponentReference