Chris Stewart
Chris Stewart

Reputation: 1679

Get Values from a Slick 2.0 Query in a case class form

I am trying to get an underlying querys case classes from a Scala Slick query, and it seems more difficult to me than it should be. Here is my compiler error:

[info] Compiling 18 Scala sources to /home/target/scala-2.11/classes... [error] /home/src/main/scala/com/core/address/AddressDAO.scala:30: type mismatch; [error] found : scala.slick.lifted.Query[com.core.address.AddressDAO,com.core.protocol.Address,Seq] [error] required: Option[com.core.protocol.Address] [error] q

Here is the method I have written:

  def getAddress(otherAddress: String): Future[Option[Address]] = {
    future {
      val q = for (addr <- addresses if (addr.address == otherAddress)) yield addr
      q
    }

Here is the Slick Schema:

class AddressDAO(tag: Tag) extends Table[Address](tag, "ADDRESSES") with DbConfig {

  def address = column[String]("ADDRESS", O.PrimaryKey)
  def hash160 = column[String]("HASH160")
  def n_tx = column[Long]("N_TX")
  def total_received = column[Double]("TOTAL_RECEIVED")
  def total_sent = column[Double]("TOTAL_SENT")
  def final_balance = column[Double]("FINAL_BALANCE")
  def * = (hash160, address, n_tx, total_received, total_sent, final_balance) <> (Address.tupled, Address.unapply)

}

What I want to do is expressed in the return type of the method getAddress which is Future[Option[Address]]. I want the first element that the database is finding. The type that is actually being returned is of type scala.slick.lifted.Query[com.core.address.AddressDAO,com.core.protocol.Address,Seq]

There does not seem to be any execute method or anything to kick start the query. I suspect this can be done with for-comprehensions but I cannot figure how to actually do it.

Thanks!

Upvotes: 0

Views: 166

Answers (2)

Vidya
Vidya

Reputation: 30310

I am certainly no Slick expert, but after a quick perusal of the docs, I am wondering if maybe wrapping something like this in your Future would work:

addresses.filter(_.address === "givenAddressString").firstOption

Upvotes: 1

Ashalynd
Ashalynd

Reputation: 12563

You have to actually run your query.

q.firstOption is what you probably want to use:

def getAddress(otherAddress: String): Future[Option[Address]] = {
    future {
      val q = for (addr <- addresses if (addr.address == otherAddress)) yield addr
      q.firstOption
    }

PS. Simply filtering addresses for the given value of address is indeed more concise. And of course the performance of this query depends on whether you have an index on that field and the size of your table :)

Upvotes: 1

Related Questions