Trying to get all records from 2 weeks ago

2019-09-05 00:56发布

问题:

I'm trying to get all records from a table that were created 2 weeks ago.

My method looks like this:

 def getRecent(from: Instant): Future[Seq[User]] = {
    db.run(
      users.filter(f => f.status != 0 && f.createdAt > from ).sortBy(_.id.desc).result
    )
  }

I have an implicit already that I thought would work but I guess it is only for reading rows:

class UsersTable(tag: Tag) extends Table[User](tag, "users") {

    implicit val dateColumnType = MappedColumnType.base[Instant, Timestamp](
      i => Timestamp.from(i),
      ts => {
        ts.toInstant

      }
    )

    def id = column[Int]("id", O.PrimaryKey)
    ....

The error is:

 value > is not a member of slick.lifted.Rep[java.time.Instant]

回答1:

Actually you are nearly there. It is used for both read and writes. But here is the thing: it needs to be in scope (even for your filtering).

Plain Slick solution

Just put your conversion into companion object like this:

object UserTable {
    implicit val dateColumnType = MappedColumnType.base[Instant, Timestamp](
      i => Timestamp.from(i),
      ts => {
        ts.toInstant

      }
    )
}

and then do this:

def getRecent(from: Instant): Future[Seq[User]] = {
    // I added this import here
    import UserTable.dateColumnType

    db.run(
      users.filter(f => f.status != 0 && f.createdAt > from ).sortBy(_.id.desc).result
    )
 }

Play-Slick solution

Above answer doesn't really fit play-slick part which is not explicitly stated in the question (though question is tagged with playframework tag). If you are using play-slick than your approach would be something like this:

Put your conversation into trait (trait DbImplicits) that require to be mixed-in together with or extends HasDatabaseConfigProvider.

trait DbImplicits { self: HasDatabaseConfigProvider[JdbcProfile] =>
  import self.driver._

    implicit val dateColumnType = MappedColumnType.base[Instant, Timestamp](
        i => Timestamp.from(i),
        ts => {
           ts.toInstant
        }
    )
}

Later use it like this:

class MyClassUsingImplicits @Inject()(
    protected val dbConfigProvider: DatabaseConfigProvider
) extends HasDatabaseConfigProvider[JdbcProfile] 
  with DbImplicits {
  import driver._

  // your further code comes here
}

EDIT: BTW I just noticed another mistake in this fragment:

f.status != 0

You should be using Slick operator:

f.status =!= 0