2013-06-15 2 views
4

Grails упрощает до get объект домена по ID (удобен для создания REST API).GORM получить/найти ресурс по ID используя MongoDB в Grails

Контроллер для извлечения ресурса может быть столь же просто, как:

MetricController.groovy

import grails.converters.JSON 

class MetricController { 

    def index() { 
     def resource = Metric.get(params.id) 
     render resource as JSON 
     } 

    } 


При использовании плагин Grails для MongoDB GORM (compile ":mongodb:1.2.0"), тип по умолчанию id от Longneeds to be changed до типа String или ObjectId.

Metric.groovy

import org.bson.types.ObjectId 

class Metric { 
    static mapWith = "mongo" 
    ObjectId id 
    String title 
    } 


Однако делать .get(1) теперь будет приводить:

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


Я принял догадку и изменил контроллер использовать findById:

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

Это исправило ошибку, но не удалось найти объект (всегда возвращает null).

Например, используя идентификатор «-1387348672» не находит этот тестовый объект:

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


ObjectId.inc поля не может даже быть правильным полем использовать для идентификатора ресурса.

Итак, что является самым простым способом получить объект домена по ID при использовании MongoDB?

ответ

3

Когда объект домена сохраняется в MongoDB, он хранится как документ с ObjectId как уникальный 12-байтовый первичный ключ BSON. Например, если у вас есть объект домена Product как

import org.bson.types.ObjectId 
class Product { 
    ObjectId id 
    String name 

    static mapWith = "mongo" 
} 

затем сохраненное лицо в MongoDB будет выглядеть, как показано ниже, если вы сохраните с именем «TestProduct».

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

_id становится вашим первичным ключом для этого документа. К get этот документ вам нужен первичный ключ ObjectId. Говоря из контекста RESTful, вы по крайней мере нуждаетесь в шестнадцатеричном коде 12 байтов 51bd047c892c8bf0b3a58b21 как часть запроса.

Таким образом, в приведенном выше случае, вы можете получить этот конкретный документ, делая что-то вроде

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

Посмотрите на API for ObjectId, которые сделали бы ясно, как получить документ.

Когда вы извлекаете документ как JSON, он просто показывает класс ObjectId с его элементами.

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

Зная, что идентификатор должен быть ключ шестигранный BSON 12-байтовый получил меня в правильном направлении. Оказалось, что довольно легко создавать строки идентификаторов из ObjectIDs ... просто используйте '.toString()'. И затем вы можете передать строку ID непосредственно в '.get()', если строка идентификатора отформатирована правильно ('[0-9a-f] {24}'). –

2

Для полноты информации, здесь находится домен с контроллером для получения ресурса по строке ID (вместо ObjectID). Пример: Metric.get("51bf8ccc30040460f5a05579")

Домен

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 
     ] 
     } 

    } 

Метод out() используется для отображения ресурса с указанием его идентификатора строки (а не его ObjectID).

Контроллер

import grails.converters.JSON 

class MetricController { 

    def index() { 
     def resource = Metric.read(params.id) 
     render resource.out() as JSON 
     } 

    } 


Пример ответа на/rest/metric/51bf8ccc30040460f5a05579

{ "id": "51bf8ccc30040460f5a05579", "title": "Accounts" }