GORM get / find a resource by ID using MongoDB in Grails

Grails makes it easy to get a domain object by ID (it is convenient for creating a REST API).

A controller for retrieving a resource can be as simple as:

MetricController.groovy

import grails.converters.JSON class MetricController { def index() { def resource = Metric.get(params.id) render resource as JSON } } 


When using the Grails plugin for MongoDB GORM ( compile ":mongodb:1.2.0" ), you need to change the id type to enter String or ObjectId .

Metric.groovy

 import org.bson.types.ObjectId class Metric { static mapWith = "mongo" ObjectId id String title } 


However, executing .get(1) will result in:

 Error 500: Internal Server Error URI /bow/rest/metric/1 Class java.lang.IllegalArgumentException Message invalid ObjectId [1] 


I made an assumption and changed the controller to use findById :

 def resource = Metric.findById(new ObjectId(new Date(), params.id.toInteger())) 

This fixed the error, but could not find the object (always returns null).

For example, using the identifier "-1387348672" does not find this test object:

 { "class" : "Metric", "id" : { "class" : "org.bson.types.ObjectId", "inc" : -1387348672, "machine" : 805582250, "new" : false, "time" : 1371329632000, "timeSecond" : 1371329632 }, "title" : "Test" } 


The ObjectId.inc field may not even be the right field to use the resource identifier.

So, what is the easiest way to get a domain object by ID when using MongoDB?

+4
source share
2 answers

When a domain object is stored in MongoDB, it is stored as a document with ObjectId as a unique 12 byte BSON primary key. For example, if you have a Product domain object, for example

 import org.bson.types.ObjectId class Product { ObjectId id String name static mapWith = "mongo" } 

then the saved object in MongoDB will look lower if you save it with the name "TestProduct".

 //db.product.find() in mongodb { "_id" : ObjectId("51bd047c892c8bf0b3a58b21"), "name" : "TestProduct", "version" : 0 } 

_id becomes your primary key for this document. To get this document you need the primary key ObjectId. Speaking from a RESTful context, you at least need 12 byte hex code 51bd047c892c8bf0b3a58b21 as part of the request.

So, in the above example, you can get this specific document by doing something like

 Product.get(new ObjectId("51bd047c892c8bf0b3a58b21")) Product.findById(new ObjectId("51bd047c892c8bf0b3a58b21")) 

Take a look at the API for ObjectId , which will make it clear how to get the document.

When you retrieve the document as JSON, it just shows the ObjectId class with its elements.

 { "class": "com.example.Product", "id": { "class": "org.bson.types.ObjectId", "inc": -1280996575, "machine": -1993569296, "new": false, "time": 1371341948000, "timeSecond": 1371341948 }, "name": "TestProduct" } 
+3
source

For completeness, here is a domain with a controller to get a resource by ID line (instead of ObjectID). Example: Metric.get("51bf8ccc30040460f5a05579")

Domain

 import org.bson.types.ObjectId class Metric { ObjectId id String title static mapWith = "mongo" def out() { return [ id: id as String, //convert Mongo ObjectId to 12-byte hex BSON title: title ] } } 

The out() method is used to render a resource showing its identification string (and not its ObjectID).

controller

 import grails.converters.JSON class MetricController { def index() { def resource = Metric.read(params.id) render resource.out() as JSON } } 


Response example for /rest/metric/51bf8ccc30040460f5a05579

 { "id": "51bf8ccc30040460f5a05579", "title": "Accounts" } 
+3
source

Source: https://habr.com/ru/post/1486436/


All Articles