0

I am using Reactive Mongo version 0.11.11 and I want to implement a method in my DAO which counts all documents by _id.

Here is my DAO:

import com.google.inject.Inject
import models.auth.{Team, Player}
import play.api.libs.concurrent.Execution.Implicits.defaultContext
import play.api.libs.json._
import play.modules.reactivemongo.ReactiveMongoApi
import play.modules.reactivemongo.json._
import reactivemongo.bson._
import reactivemongo.play.json.collection.JSONCollection

import scala.concurrent.Future

trait TeamDao {
  def find(_id: BSONObjectID): Future[Option[Team]]

  def find(name: String): Future[Option[Team]]

  def save(team: Team): Future[Team]

  def link(player: Player, team: Team): Future[Team]

  def update(team: Team): Future[Team]

  def count(team: Option[Team] = None): Future[Int]

  def count(_id: BSONObjectID): Future[Int]

  def countAllPlayersWithTeam(team: Team): Future[Int]
}

class MongoTeamDao @Inject()(reactiveMongoApi: ReactiveMongoApi) extends TeamDao {

  val players = reactiveMongoApi.db.collection[JSONCollection]("players")
  val teams = reactiveMongoApi.db.collection[JSONCollection]("teams")

  def find(_id: BSONObjectID): Future[Option[Team]] = teams.find(BSONDocument("_id" -> _id)).one[Team]

  def find(name: String): Future[Option[Team]] = teams.find(Json.obj("name" -> name)).one[Team]

  def save(team: Team): Future[Team] = teams.insert(team).map(_ => team)

  def link(player: Player, team: Team) = for {
    _ <- players.update(Json.obj("_id" -> player.id), Json.obj("$push" -> BSONDocument("teams" -> team._id)))
    team <- find(team._id.get)
  } yield team.get


  def update(team: Team) = for {
    _ <- teams.update(BSONDocument("_id" -> team._id), BSONDocument("$set" -> BSONDocument("name" -> team.name)))
    team <- find(team._id.get)
  } yield team.get


  def count(team: Option[Team] = None): Future[Int] = {
    val tmpTeam: Team = team.getOrElse {
      return teams.count()
    }
    teams.count(Some(Json.obj("name" -> tmpTeam.name)))
  }

  def count(_id: BSONObjectID): Future[Int] = {
    teams.count(Some(Json.obj("_id" -> _id)))
  }

  def countAllPlayersWithTeam(team: Team): Future[Int] = {
    players.count(Some(Json.obj("teams" -> team._id)))
  }

}

The problem is that I get the following error:

value BSONObjectIDFormat in trait BSONFormats is deprecated: Use [[reactivemongo.play.json.BSONFormats.BSONObjectIDFormat]]
[error]     teams.count(Some(Json.obj("_id" -> _id)))

I tried to replace the count method with:

def count(_id: BSONObjectID): Future[Int] = {
 teams.count(Some(BSONDocument("_id" -> _id))) 
}

But then I get the following compile error:

[error]  found   : reactivemongo.bson.BSONDocument
[error]  required: MongoTeamDao.this.teams.pack.Document
[error]     (which expands to)  play.api.libs.json.JsObject
[error] Error occurred in an application involving default arguments.
[error]     teams.count(Some(BSONDocument("_id" -> _id)))
John Doe
  • 275
  • 3
  • 12

1 Answers1

1

You are mixing JSONCollection and BSON values.

It's recommanded that you either use the JSON serialization with JSONCollection, or you use the default BSON serialization with BSONCollection.

The deprecation message is a warning indicating to use the separate JSON library, instead of the former types previously included in the Play plugin.

A BSONCollection can be resolved from the Play plugin as follows.

reactiveMongoApi.database.map(_.collection[BSONCollection]("players"))

The functions MongoConnection.(db|apply) and/or ReactiveMongoApi.db are deprecated, and the equivalent .database must be used (which returns Future[DefaultDB] instead of DefaultDB).

cchantep
  • 9,118
  • 3
  • 30
  • 41
  • Thank you for your help! I am using Silhouette and I need to persist `LoginInfo` as part of a `Player` document. Now the problem is, that in the class `LoginInfo` there is only `implicit val jsonFormat = Json.format[LoginInfo]` and therefore I get a type error, because I am now handling BSON and not JSON. Do you have any idea if I can make a BSON out of a JSON or am I missing something? – John Doe May 29 '16 at 15:14
  • Well, the only reason why I am handling BSON now is because I need to map somehow `_id`. Unfortunately, there is no JSON substitute for `BSONObjectID`, is there? – John Doe May 29 '16 at 15:18
  • If you read the [doc](http://reactivemongo.org/releases/0.11/documentation/json/overview.html), you can see that when using JSON, the representation for a `BSONObjectID` is a `JsObject` with `$oid`, and that conversion for that is provided by `import reactivemongo.play.json._` – cchantep May 29 '16 at 18:53
  • Thank you for your help! – John Doe May 29 '16 at 19:16