GORM使用Grails中的MongoDB按ID获取/查找资源

时间:2013-06-15 22:18:50

标签: mongodb rest grails gorm objectid

Grails可以通过ID轻松get域对象(方便构建REST API)。

检索资源的控制器可以简单如下:

MetricController.groovy

import grails.converters.JSON

class MetricController {

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

   }


使用MongoDB GORM的Grails插件(compile ":mongodb:1.2.0")时,默认id类型Long needs to be changed要输入StringObjectId。< / p>

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)。

例如,使用id“-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时,按ID检索域对象的最简单方法是什么?

2 个答案:

答案 0 :(得分:4)

当域对象在MongoDB中持久化时,它将存储为具有ObjectId作为唯一12字节BSON主键的文档。例如,如果您有一个域对象Product,如

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

    static mapWith = "mongo"
}

如果使用名称“TestProduct”保存,MongoDB中的持久化实体将如下所示。

//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 :(得分:3)

为了完整性,这里是带有控制器的域,通过 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()方法用于呈现显示其ID字符串(而不是其ObjectID)的资源。

<强>控制器

import grails.converters.JSON

class MetricController {

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

   }


/rest/metric/51bf8ccc30040460f5a05579

的JSON响应示例
{ "id": "51bf8ccc30040460f5a05579", "title": "Accounts" }