4

MongoDB で地理空間クエリを実行するには、場所を含むドキュメント (2dまたは2dsphere地理空間インデックスを含む) は次のようになります。

{
    _id: …,
    loc: {
        type: "Point",
        coordinates: [ <longitude>, <latitude> ]
    }
}

私は Scala、ReactiveMongo、および Play Framework に非常に慣れていませんが、私の意見では、そのような場所を使用する明白な方法は、次のようなケース クラスを使用することです。

case class Point(lon: Double, lat: Double)

また、Web サイトの API が扱う JSON 表現は次のようになります。

{
    _id: …
    loc: [ <longitude>, <latitude> ]
}

今、ReactiveMongo モデルにこれらのフォーマット間でシリアル化/逆シリアル化するように指示する方法がわかりません。

私のコントローラーは次のようになります。

package controllers

import play.api._
import play.api.mvc._
import play.api.libs.json._
import scala.concurrent.Future

// Reactive Mongo imports
import reactivemongo.api._
import scala.concurrent.ExecutionContext.Implicits.global

// Reactive Mongo plugin
import play.modules.reactivemongo.MongoController
import play.modules.reactivemongo.json.collection.JSONCollection

object Application extends Controller with MongoController {
    def collection: JSONCollection = db.collection[JSONCollection]("test")

    import play.api.data.Form
    import models._
    import models.JsonFormats._

    def createCC = Action.async {
        val user = User("John", "Smith", Point(-0.0015, 51.0015))
        val futureResult = collection.insert(user)
        futureResult.map(_ => Ok("Done!"))
    }
}

PointWriter と PointReader を使用しようとしました。これは私のmodels.scalaです:

package models

import reactivemongo.bson._
import play.modules.reactivemongo.json.BSONFormats._

case class User(
    // _id: Option[BSONObjectID],
    firstName: String,
    lastName: String,
    loc: Point)

case class Point(lon: Double, lat: Double)

object Point {
    implicit object PointWriter extends BSONDocumentWriter[Point] {
        def write(point: Point): BSONDocument = BSONDocument(
            "type" -> "Point",
            "coordinates" -> Seq(point.lat, point.lon)
        )
    }

    implicit object PointReader extends BSONReader[BSONDocument, Point] {
        def read(doc: BSONDocument): Point = Point(88, 88)
    }
}

object JsonFormats {
    import play.api.libs.json.Json
    import play.api.data._
    import play.api.data.Forms._

    import play.api.libs.json._
    import play.api.libs.functional.syntax._

    implicit val pointFormat = Json.format[Point]
}

コントローラー アクションを呼び出すとcreateCC、適切にフォーマットされた Point オブジェクトが新しく作成されたドキュメントになると予想されますが、実際に得られるのは次のようなものです。

{
    "_id": ObjectId("52ac76dd1454bbf6d96ad1f1"),
    "loc": {
        "lon": -0.0015,
        "lat": 51.0015 
    }
}

したがって、そのようなオブジェクトをデータベースに書き込む方法を ReactiveMongoに使用PointWriterして指示しようとしても、まったく効果がありません。PointReaderPoint

私がしなければならないことを理解するのを手伝ってくれる人はいますか?

(私は PHP のバックグラウンドを持っており、Scala について理解を深めようとしています...)

更新: tmbo の回答のおかげで、このライターを思いつきました:

val pointWrites = Writes[Point]( p =>
    Json.obj(
        "type" -> JsString("Point"),
        "coordinates" -> Json.arr(JsNumber(p.lon), JsNumber(p.lat))
    )
)
4

1 に答える 1