Grails mongoDB - Collections of DBRefs Inside an Embedded Collection
I’m working on a project where we’re migrating from MySQL to mongoDB. One of the reasons for the switch is that the use of embedded collections will simplify our model and make it more efficient. The official mongodb-plugin (1.0.0.RC1) has some problems before it will be ready for production though. One of the problems is that having an embedded collection referencing another collection isn’t possible with GORM (GPMONGODB-92). The workaround is to use the Low-level API instead of GORM. Here’s a simple example where a building has many offices and the offices has companies, but the companies need to be in an own collection since we need the possibility to query them specificaly.
Only tested with Grails 2.0.0.RC1 and mongodb plugin 1.0.0.RC1
importcom.mongodb.DBRefimportcom.gmongo.GMongodefmongo=newGMongo("127.0.0.1",27017)// Get a db reference in the old fashion way. Could use def mongo inside of a controller or service.defdb=mongo.getDB("foo")// Create a building defbuilding=newBuilding(name:"Stockholm business centre",offices:[]).save()// Add someone elses officebuilding.offices<<newOffice(name:"Bill Gates not so cool workplace",companies:[])// Add my officebuilding.offices<<newOffice(name:"Andreas awesome workplace",companies:[])building.save(flush:true)// Create a companydefcompany=newCompany(name:"Andreas inc").save()// Get the referencedefcompanyRef=newDBRef(db,"company",company.id)// Add company to office. Building.collection.update(['_id':building.id,'offices.name':'Andreas awesome workplace'],[$set:['offices.$.companies':[companyRef]]])// QUERYING// Since the embedded collection doesn't have an identifier, find it's index in the list.defmyOfficeIndex=building.offices.findIndexOf{it.name=="Andreas's awesome workplace"}// The DBRef isn't available in GORM even though it's persistedassertbuilding.offices[myOfficeIndex].companies==[]// Finding companies through the embedded collection using low level api.defmyOfficeCompanies=Building.collection.findOne('_id':building.id).offices[myOfficeIndex].companiesassertcompany.idinmyOfficeCompanies*.id