GORM 在 Grails 中使用 MongoDB 按 ID 获取/查找资源
Posted
技术标签:
【中文标题】GORM 在 Grails 中使用 MongoDB 按 ID 获取/查找资源【英文标题】:GORM get/find resource by ID using MongoDB in Grails 【发布时间】:2013-06-12 06:43:51 【问题描述】: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 (compile ":mongodb:1.2.0"
) 的 Grails 插件时,默认将 id
类型的 Long
needs 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”的id找不到这个测试对象:
"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 检索域对象的最简单方法是什么?
【问题讨论】:
【参考方案1】:当域对象被持久化在 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"
【讨论】:
知道 ID 应该是 12 字节的十六进制 BSON 密钥让我找到了正确的方向。事实证明,从 ObjectID 生成 ID 字符串非常容易……只需使用.toString()
。然后只要ID字符串格式正确([0-9a-f]24
),就可以直接将ID字符串传递给.get()
。【参考方案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()
方法用于呈现显示其 ID 字符串(而不是其 ObjectID)的资源。
控制器
import grails.converters.JSON
class MetricController
def index()
def resource = Metric.read(params.id)
render resource.out() as JSON
示例 JSON 响应 /rest/metric/51bf8ccc30040460f5a05579
"id": "51bf8ccc30040460f5a05579", "title": "Accounts"
【讨论】:
以上是关于GORM 在 Grails 中使用 MongoDB 按 ID 获取/查找资源的主要内容,如果未能解决你的问题,请参考以下文章