如何使用Reactivemongo在Play框架中处理MongoDB ObjectIds?

时间:2015-03-06 19:10:41

标签: json mongodb playframework reactivemongo

我有一个带案例类的基本模型

case class Record( id: Option[String], 
                 data: Double,
                 user: String,
                 )

object RecordJsonFormats {
  import play.api.libs.json.Json

  implicit val recordFormat = Json.format[Record]
}

字段user实际上是其他模块的ObjectIdid也是ObjectId,然后尝试将String类型更改为BSONObjectId } play.api.libs.json.Json中的宏中断...因此userid保存的字段都保存为String而不是ObjectId

在Play框架中使用ObjectIds进行操作的最佳方式是什么?

  • 也许我应该使用play.api.libs.json.Json
  • 延长BSONObjectId
  • 也许有一种方法可以自动跟踪模型和ID,而无需在模型中声明它们?

3 个答案:

答案 0 :(得分:2)

MongoDB有一个ObjectId类型的默认 _id 字段,它唯一地标识给定集合中的文档。但是,此 _id 通常在应用程序域的上下文中没有语义含义。因此,一个好的做法是引入一个额外的 id 字段作为文档索引。 id 只能是一个长数字,不多或少。

然后,您可以轻松地通过 id 搜索文档,而不关心ObjectId。

这是https://github.com/luongbalinh/play-mongo/,是使用Play 2.4.x和ReactiveMongo的示例项目。希望它能帮到你。

答案 1 :(得分:2)

您可以覆盖默认的_id类型。您只需在案例类中指定所需的类型即可。

import java.util.UUID
import play.api.libs.json._

case class Record (_id: UUID = UUID.randomUUID())

object Record {
  implicit val entityFormat = Json.format[Record]
}

答案 2 :(得分:0)

对于使用Official Mongo Scala驱动程序和Play Framework 2.6+的用户,这是我的解决方案:https://gist.github.com/ntbrock/556a1add78dc287b0cf7e0ce45c743c1

import org.mongodb.scala.bson.ObjectId
import play.api.libs.json._
import scala.util.Try

object ObjectIdFormatJsonMacro extends Format[ObjectId] {

  def writes(objectId: ObjectId): JsValue = JsString(objectId.toString)
  def reads(json: JsValue): JsResult[ObjectId] = json match {
    case JsString(x) => {
      val maybeOID: Try[ObjectId] = Try{new ObjectId(x)}
      if(maybeOID.isSuccess) JsSuccess(maybeOID.get) else {
        JsError("Expected ObjectId as JsString")
      }
    }
    case _ => JsError("Expected ObjectId as JsString")
  }
}

在您的业务对象中像这样使用它:

case class BusinessTime(_id: ObjectId = new ObjectId(), payRate: Double)

object BusinessTime {
  implicit val objectIdFormat = ObjectIdFormatJsonMacro
  implicit val businessTimeFormat = Json.format[BusinessTime]
}