【问题标题】:Optimal way to read out JSON from MongoDB into a Scalatra API从 MongoDB 读取 JSON 到 Scalatra API 的最佳方式
【发布时间】:2013-08-22 21:36:08
【问题描述】:

我有一个预先格式化的 JSON blob 作为一个字符串存储在 MongoDB 中,作为一个集合中的一个字段。目前在我基于 Scalatra 的 API 中,我有一个前置过滤器,它使用 JSON 内容类型呈现我的所有响应。我如何返回内容的示例如下所示:

   get ("/boxscore", operation(getBoxscore)) {
        val game_id:Int = params.getOrElse("game_id", "3145").toInt
        val mongoColl = mongoDb.apply("boxscores")
        val q: DBObject = MongoDBObject("game_id" -> game_id)
        val res = mongoColl.findOne(q)
        res match {
            case Some(j) => JSON.parseFull(j("json_body").toString) 
            case None => NotFound("Requested document could not be found.")
        }
    }

现在这确实有效。这似乎不是“Scala”的做事方式,我觉得这可以优化。让我担心的是,当我添加一个缓存层并且缓存没有命中时,我花费了额外的 CPU 时间来重新解析我已经在 MongoDB 中格式化为 JSON 的字符串:

JSON.parseFull(j("json_body").toString)

我必须从 findOne() 中获取结果,在其上运行 .toString,然后将其重新解析为 JSON。有没有更优的路线?由于 JSON 已经作为字符串存储在 MongoDB 中,我猜测序列化程序/案例类在这里不是正确的解决方案。当然,我可以留下这里的东西 - 但我想知道是否有一种方法可以更类似于 Scala 并且对 CPU 更友好。

【问题讨论】:

  • 由于 JSON 只是一个字符串 - 你不能从你的视图中返回字符串吗?

标签: json mongodb scala scalatra casbah


【解决方案1】:

可以选择通过处理 MongoDB 类来扩展 Scalatra 的渲染管道。以下两条路线作为示例。他们返回 MongoCursorDBObject 作为结果。我们要将它们转换为字符串。

get("/") {
  mongoColl.find
}

get("/:key/:value") {
  val q = MongoDBObject(params("key") -> params("value"))
  mongoColl.findOne(q) match {
    case Some(x) => x
    case None => halt(404)
  }
}

为了处理类型,我们需要定义一个偏函数来处理转换并设置适当的内容类型。

有两种情况,第一种处理DBObject。内容类型设置为“application/json”,并通过调用toString方法将对象转换为字符串。第二种情况处理MongoCursor。由于它实现了TraversableOnce,因此可以使用map函数。

def renderMongo = {
  case dbo: DBObject =>
    contentType = "application/json"
    dbo.toString

  case xs: TraversableOnce[_] => // handles a MongoCursor, be aware of type erasure here
    contentType = "application/json"
    val ls = xs map (x => x.toString) mkString(",")
    "[" + ls + "]"

}: RenderPipeline

(注意以下类型定义:type RenderPipeline = PartialFunction[Any, Any]

现在需要挂钩该方法。处理 HTTP 调用后,结果将转发到渲染管道以进行进一步转换。可以通过覆盖ScalatraBase 中的renderPipeline 方法来添加自定义处理。使用以下定义,首先调用renderMongo 函数:

override protected def renderPipeline = renderMongo orElse super.renderPipeline

这是处理 MongoDB 类型的基本方法。还有其他选项,例如使用json4s-mongo

Here 是工作示例项目中的先前代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-11
    • 1970-01-01
    • 1970-01-01
    • 2021-07-17
    • 1970-01-01
    • 2020-03-20
    • 1970-01-01
    • 2012-01-30
    相关资源
    最近更新 更多