John M
John M

Reputation: 1479

How to support embedded maps (with custom value types) in MongoDB GORM?

I would like to have an embedded document referred to by a map (as in 'class A' below). The environment is Grails + GORM + MongoDB.

is that possible, and if yes, how?

class A { // fails with IllegalArgumentException occurred when processing request: can't serialize class X in line 234 of org.bson.BasicBSONEncoder
    static mapWith = "mongo"
    Map<String, X> map = new HashMap<String, X>()
}

class B { // works
    static mapWith = "mongo"
    List<X> list = new ArrayList<X>()
}

class C { // works with primitive type values
    static mapWith = "mongo"
    Map<String, String> map = new HashMap<String, String>()
}

class X {
    String data

    public X(String data) {
        this.data = data
    }
}

Upvotes: 2

Views: 2055

Answers (2)

Lucas T
Lucas T

Reputation: 671

The embedding works perfectly,as Art Hanzel advised.

However your problem comes from the fact that you try and use List genericity as a sort of constraint :

Map<String, X>

The problem is that Grails couldn't cope well with this syntax, first because Groovy doesn't support genericity.

However, the MongoDB plugin offers a very powerful functionality that lets you define custom type as Domain Class Properties : see here.

In your case you could have

class A {
    static mapWith = "mongo"
    MyClass map = new MyClass()
}

Then in your src/java for example you could for example implement a

class MyClass extends HashMap<String,X> { }

Then, of course, you have to define a special AbstractMappingAwareCustomTypeMarshaller to specify how to read and write the property in the DB.

An additional step could also be to add a custom validator to class A to check the validity of data...

Upvotes: 3

user915495
user915495

Reputation:

The MongoDB Grails plugin documentation describes how to make embedded documents:

class Foo {
    Address address
    List otherAddresses
    static embedded = ['address', 'otherAddresses']
}

Off the top of my head, you should be able to access these via the object graph. I don't see any reason why you shouldn't.

myFoo.address.myAddressProperty...

Upvotes: 0

Related Questions