mongodbscalareactivemongo

ReactiveMongo with generics: "ambiguous implicit values"


I'm not really sure where this error is coming from. I'm trying to migrate from an old .find() method where I could pass Pattern: query: BSONDocument to find and call .one[T] on it. This worked perfectly fine, but I'd like to follow the recommendations.

However, I have a feeling that my desire to create a generic database access object is causing some of this headache... take a look below.

The object that i'm trying to read from:

package Models

import reactivemongo.api.bson.{BSONDocumentHandler, Macros}

case class Person(name: String)

object Person {
  implicit val handler: BSONDocumentHandler[Person] = Macros.handler[Person]
}

The class containing the method I'm trying to execute (ignore the Await, etc.)

package Data

import reactivemongo.api.AsyncDriver
import reactivemongo.api.bson._
import reactivemongo.api.bson.collection.BSONCollection
import reactivemongo.api.commands.WriteResult

import scala.concurrent.{Await, Future}
import scala.concurrent.duration._
import scala.reflect.ClassTag

object DataService extends DataService

trait DataService {
  implicit val ec: scala.concurrent.ExecutionContext = scala.concurrent.ExecutionContext.global
  private val driver = new AsyncDriver
  private val connection = Await.result(driver.connect(List("localhost:32768")), 10.seconds)
  private val database = Await.result(connection.database("database"), 10.seconds)

  private def getCollection[T]()(implicit tag: ClassTag[T]): BSONCollection = database.collection(tag.runtimeClass.getSimpleName)

  def Get[T]()(implicit handler: BSONDocumentHandler[T], tag: ClassTag[T]): Future[Option[T]] = {
    val collection = getCollection[T]
    collection.find(BSONDocument("name" -> "hello"), Option.empty).one[T]
  }
}

How I'm trying to get it (ignore the Await, this is just for test purposes):

val personName = Await.result(dataService.Get[Person](), 10.seconds).map(_.name).getOrElse("Not found")

The error that I'm getting:

Error:(32, 19) ambiguous implicit values:
 both object BSONDocumentIdentity in trait BSONIdentityHandlers of type reactivemongo.api.bson.package.BSONDocumentIdentity.type
 and value handler of type reactivemongo.api.bson.BSONDocumentHandler[T]
 match expected type collection.pack.Writer[J]
   collection.find(BSONDocument("name" -> "hello"), Option.empty).cursor[T]

Thank you all for your help.


Solution

  • Try to add type to your option in your second argument find method, for example:

    def Get[T]()(implicit handler: BSONDocumentHandler[T], tag: ClassTag[T]): Future[Option[T]] = {
      val collection = getCollection[T]
      collection.find(BSONDocument("name" -> "hello"), Option.empty[BSONDocument]).one[T]
    }