1

Scala プロジェクトで MongoDB からドキュメントを適切にシリアル化する方法を見つけようとしています。ここで私が抱えている問題は、ドキュメントに Array フィールドがある場合に何をすべきか、Scala でそれをどのように扱うべきかがわからないことです。MongoDB でのドキュメントの外観は次のとおりです。

> db.injuries.findOne()
{
    "_id" : ObjectId("5220ef71bbf8af333d000001"),
    "team_id" : 86,
    "league" : "NFC",
    "team_name" : "Arizona Cardinals",
    "players" : [
        {
            "player_id" : 9864,
            "date" : "8/26/2013",
            "position" : "TE",
            "name" : "Rob Housler",
            "injury" : "is doubtful for 9/8 against St. Louis",
            "status" : "Doubtful",
            "fantasy" : "",
            "injured" : "True",
            "type" : "ankle"
        },
        {
            "player_id" : 11610,
            "date" : "8/25/2013",
            "position" : "G",
            "name" : "Jonathan Cooper",
            "injury" : "may be placed on injured reserve",
            "status" : "Out",
            "fantasy" : "",
            "injured" : "True",
            "type" : "leg"
        },
        {
            "player_id" : 9126,
            "date" : "4/3/2013",
            "position" : "LB",
            "name" : "Daryl Washington",
            "injury" : "will be eligible to return on 10/6 against Carolina",
            "status" : "Suspended",
            "fantasy" : "",
            "injured" : "True",
            "type" : "four-game suspension"
        }
    ],
    "updated_at" : ISODate("2013-08-30T19:16:01.466Z"),
    "created_at" : ISODate("2013-08-30T19:16:01.466Z")
}
> 

ここで、ケース クラスを作成して、このドキュメントのカスタム シリアライザーを作成し、それをクライアントに配信できるようにする必要があります。次のようなケースクラスの構築を開始しました。

case class Injury(_id: ObjectId = new ObjectId, team_id: Int, team_name: String, league: String, players: List[????], created_at: Option[Date] = None, updated_at: Option[Date] = None, id: Option[ObjectId] = None )

コンテキストに応じて他のコレクションではプレーヤー ハッシュが異なって見えるため、必ずしもプレーヤー ケース クラスを作成する必要はありません。「スケジュール」コレクションなどのプレーヤーの配列があるかもしれませんが、そこに負傷データをリストするつもりはありません。これはプレーヤー コレクションへの実際の参照ではなく、フィールドの名前が「players」であるハッシュを含む単なるリストです。理想的には、このチームの ID が要求されたときにこれを単純に出力するシリアル化を作成する方法を理解できます。

{
  "team_id": 86,
  "team_name": "Arizona Cardinals",
  "players": [
    {
      "player_id": 9864,
      "date": "8/26/2013",
      "position": "TE",
      "name": "Rob Housler",
      "injury": "is doubtful for 9/8 against St. Louis",
      "status": "Doubtful",
      "fantasy": "",
      "injured": "True",
      "type": "ankle"
    },
    {
      "player_id": 11610,
      "date": "8/25/2013",
      "position": "G",
      "name": "Jonathan Cooper",
      "injury": "may be placed on injured reserve",
      "status": "Out",
      "fantasy": "",
      "injured": "True",
      "type": "leg"
    },
    {
      "player_id": 9126,
      "date": "4/3/2013",
      "position": "LB",
      "name": "Daryl Washington",
      "injury": "will be eligible to return on 10/6 against Carolina",
      "status": "Suspended",
      "fantasy": "",
      "injured": "True",
      "type": "four-game suspension"
    }
  ]
}

その最終的な JSON ドキュメントを取得できるようにするには、他に何をしなければなりませんか? Salat がケース クラスへのシリアル化を処理できることは知っていますが、ここでの player 属性の処理方法がわかりません。これが私が取り組み始めたシリアライザーの始まりですが、プレイヤーマップをここに合わせる方法はまだわかりません:

class InjurySerializer extends CustomSerializer[Injury](format => ({
  case JObject(
  ("id", JString(id)) ::
    ("team_id", JString(team_id)) ::
    ("team_name" , JString(team_name)) ::
    ("league" , JString(league)) :: Nil) =>
    Injury(new ObjectId, team_id.asInstanceOf[Int], team_name.asInstanceOf[String], league.asInstanceOf[String])
}, {
  case injury: Injury =>
    JObject.apply(
      "team_id" -> JInt(injury.team_id),
      "team_name" -> JString(injury.team_name),
      "league" -> JString(injury.league)
    )
}))

そして、すべてのドキュメントを取得するための単純なヘルパーがあります。

object Injury {

  def findAll = {
    val results = InjuryDAO.findAll
    results.map(grater[Injury].asObject(_)).toList
  }

}

これは問題なく動作しますが、上記のようにプレイヤー マップは含まれません。

4

2 に答える 2

0

おそらくここでカスタムシリアライザーを使用する必要があります。親オブジェクトへのハンドルがあると仮定します-その怪我を呼びましょう

 val playerRefs = injury.get("palyers")
 var obj = MongoDBObject("list" -> playerRefs )
 obj.as[MongoDBList]("list").toList.foreach {
   value =>
        val playerDef = value.asInstanceOf[BasicDBObject]
        // Access values from player -
        val name = playerDef.get("name")asInstanceOf[String]
        // Build your case class 
  }
于 2013-09-02T06:22:06.453 に答える
0

配列はサポートされていません。リスト、seq、その他のほぼすべてのタイプのコレクションにすると、ドキュメントは正しくシリアル化および逆シリアル化されます。

https://github.com/novus/salat/wiki/Collections

可能なすべてのフィールドを持つプレーヤー ケース クラスを作成し、デフォルト引数を使用してすべてのケースをカバーします。

カバーするさまざまなケースが多すぎる場合、それは物事が本当に醜いものになるときです. あなたは本質的に、期待される構造を持たないデータを逆シリアル化しようとしています...正確には何ですか?Map[String, Any]未解決のプル リクエストがありますが、主流の Salat にはサポートを追加していません。

于 2013-08-30T23:08:07.770 に答える