【问题标题】:GORM get/find resource by ID using MongoDB in GrailsGORM 在 Grails 中使用 MongoDB 按 ID 获取/查找资源
【发布时间】: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 键入 StringObjectId

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 检索域对象的最简单方法是什么?

【问题讨论】:

    标签: mongodb rest grails grails-orm objectid


    【解决方案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" }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-23
      • 2011-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-19
      相关资源
      最近更新 更多