⛳
【Scala】MongoScalaDriver経由で取得したDocumentをJson経由で自作クラスにマッピングする
概要
ScalaからMongoDBにアクセスするライブラリとして、MongoDB Scala Driverが用意されています。MongoDBScala Driverでは、DBとのインターフェースとしてDocumentのクラスが用意されています。使い方の概要については、【mongoDB】【Scala】mongoDB のインストール → Scala で CRUD するを参照ください。
今回はDocumentのクラスから、独自で定義したクラスにマッピングする実装をメモ書きします。
対応方針
- Documentクラスはこちらの記事にある通りJsonに変換できますので、Jsonを経由してクラスにマッピングする方針とします。
- MongoDBScalaDriverではこちらにある通り、コレクション毎のCodec機能も提供されていますが、今回は使用しない方針とします。(集計のクエリを投げるときは別途パースの処理が必要になるっぽいので)
- Jsonのパースには、PlayFrameworkの機能を使用するものとします。
- Observableを処理するためのHelperクラスについては、【mongoDB】【Scala】mongoDB のインストール → Scala で CRUD するの記事で、記載されている内容と同内容とします。
実装メモ
まずはマッピングしたいクラスと、PlayFrameworkのplay-jsonのcombinatorsで実装したJsonのパース用フォーマットを用意します。
<独自クラスとフォーマット>
import org.joda.time.DateTime
import play.api.libs.json.JodaReads.DefaultJodaDateTimeReads
import play.api.libs.json.JodaWrites.JodaDateTimeWrites
import play.api.libs.json._
import play.api.libs.functional.syntax._
object CategoryCollection {
implicit val categoryCollectionFormat = (
(__ \ "_id").format[String] ~
(__ \ "name").format[String] ~
(__ \ "register_user_id").format[String] ~
(__ \ "register_date").format[DateTime]
) (CategoryCollection.apply, unlift(CategoryCollection.unapply))
}
case class CategoryCollection(id: String = "",
name: String = "",
registerUserId: String = "",
registerDate: DateTime = DateTime.now())
上記のJsonのパース用フォーマットを使用して、クラスからドキュメントを生成してinsertします。
<ドキュメントのinsert>
object CategoryRepository {
import model.db.CategoryCollection._
import repository.MongoDBHelper._ // Helperの内容は記載割愛
// insert用のメソッド
def insertCategory(name: String, userId: String): Unit = {
// DB接続
val mongoClient = MongoClient(config.getString("mongo.db.url"))
val database = mongoClient.getDatabase(config.getString("mongo.db.database"))
val collection = database.getCollection("category")
// insert用のDocument作成
val uuid = java.util.UUID.randomUUID.toString
val nowDate = DateTime.now(DateTimeZone.UTC)
val categoryCollection = CategoryCollection(
id = uuid,
name = name,
registerUserId = userId,
registerDate = nowDate
)
// クラスからJson文字列に変換
val categoryCollectionJson = Json.toJson(categoryCollection).toString()
val document = Document(categoryCollectionJson)
// insertの発行
collection.insertOne(document)
// 接続クローズ
mongoClient.close
}
}
取得したドキュメントをJsonに変換した後に、クラスを取得します。
<ドキュメントのfind>
object CategoryRepository {
import model.db.CategoryCollection._
import repository.MongoDBHelper._ // Helperの内容は記載割愛
// find用のメソッド
def findCategory(name: String, userId: String): Seq[CategoryCollection] = {
// DB接続
val mongoClient = MongoClient(config.getString("mongo.db.url"))
val database = mongoClient.getDatabase(config.getString("mongo.db.database"))
val collection = database.getCollection("category")
// Documentの取得
val documents = collection.find(equal("register_user_id", userId)).sort(descending("register_date")).results
// 接続クローズ
mongoClient.close
// Jsonへのパース
for {
doc <- documents
category <- Json.parse(doc.toJson()).validate[CategoryCollection].asOpt
} yield category
}
}
Discussion