Reputation: 649
I'm trying to rewrite my node.js + express backend in grails. I'm using a MongoDB database, where it is common to nest fields. In my current backend I have defined a schema (using mongoose), with a field such as:
normalized: {
full_name: {type: String, trim: true, index: true}
},
I have also defined a separate, reusable schema called "locationSchema" that I can use for many of my fields, like so:
// Definition of reusable "sub-schema"
const locationSchema = new mongoose.Schema({
country: {type: String, trim: true},
region: {type: String, trim: true},
city: {type: String, trim: true},
notes: String,
latitude: {type: Number},
longitude: {type: Number}
}, {_id: false});
Which is then used, for example, to define the birth
field:
birth: {
date: {type: dateSchema, validate: dateValidator},
location: locationSchema,
notes: String
},
I did not manage to find much information on this, other than that it is possible to define nested fields as Map
s, but how would I apply constraints to the sub-fields? And how would I use "sub-schemas" in Grails?
UPDATE WITH SOLUTION
I misunderstood the use of embedded
. If you (like me) do not want to create tables/collections for embedded types, simply put the embedded class (like Location
in my case) under src/main/...
or define it in the same file as the domain class. This is stated in the documentation: http://docs.grails.org/3.1.1/ref/Domain%20Classes/embedded.html
My final, simplified solution is then:
grails-app/.../Person.groovy
class Person implements MongoEntity<Testy> {
ObjectId id
String s
Location location
static mapping = {
collection "person"
}
static embedded = ['location'] // key part that was missing
}
src/main/.../Location.groovy
package hegardt.backend.grails.model.person
import grails.validation.Validateable
class Location implements Validateable {
String country
String region
String city
String notes
Double latitude
Double longitude
static constraints = {
country nullable: true
region nullable: true
city nullable: true
notes nullable: true
latitude nullable: true
longitude nullable: true
}
}
Now I can send requests with JSON data, and the mapping and saving works correctly, as well as validation on my embedded types!
Upvotes: 0
Views: 128
Reputation: 20699
You should be using embedded object for your case.
class User {
Birth birth
static embedded = [ 'birth' ]
}
class Birth {
Date date
Location location
String notes
static constraints = {
date validator:dateValidator
}
}
Then if you do:
User u = new User()
u.birth = new Birth(...)
u.save()
the birth
will be saved as a sub-document in User
.
If you say:
new Birth(...).save()
then the GORM creates a new collection and fills the record in as usual.
Upvotes: 1