Как отфильтровать по дате в Play-SLICK, который сохраняется как мгновенный?

postgresql scala playframework slick

724 просмотра

1 ответ

416 Репутация автора

Я использую scala, play, sclick; и postgres. Я сделал таблицу с именем order& она содержит поле с именем createdв формате отметки времени с зоной. Теперь я хотел бы искать на orderоснове createdпараметров yearи monthследующим образом: -

SELECT * FROM   "order"
WHERE  created::text LIKE '2016-07%';

Приведенный выше запрос прекрасно работает в postgres.


Scala-код, для которого я написал Order:

case class Order(id: Option[Int],
                 customerId: Int,
                 amount: Double,
                 created: Option[Instant],
                 updated: Option[Instant]) extends GenericEntity {
        def this(customerId: Int,
                 amount: Double,) = this(None, customerId, amount, None, None)
}

class OrderTable(tag: Tag) extends GenericTable[Order](tag, "order") {
        override def id = column[Option[Int]]("id", O.PrimaryKey, O.AutoInc)    
        def customerId = column[Int]("customer_id")
        def amount = column[Dount]("amount")

        def customer = foreignKey("fk_order_customer", customerId, Customers.table)(_.id.getOrElse(1), onUpdate = ForeignKeyAction.Restrict, onDelete = ForeignKeyAction.Cascade)

        def * = (id, customerId, amount, created, updated) <> ((Order.apply _).tupled, Order.unapply)
}

object Orders extends GenericService[Order, OrderTable] {
        override val table = TableQuery[OrderTable]

        override def copyEntityFields(entity: Order, id: Option[Int], created: Option[Instant], updated: Option[Instant]): Order = {
          entity.copy(id = id, created = created, updated = updated)
        }

        def getMonthlyOrder(year:Int, month: Int) = {
          // execute LIKE query for the following query
          // SELECT * FROM   "order"
          // WHERE  created::text LIKE '2016-07%';
        }    
}

Где GenericEntityопределяет id, created, updated.


Так какой код я должен написать для getMonthlyOrderфункции с yearи month?

Автор: testuser Источник Размещён: 18.07.2016 06:45

Ответы (1)


1 плюс

98 Репутация автора

Вам нужны две вещи:

1) Тип столбца, чтобы Slick знал, как сохранить его в базе данных. В этом случае вы хотите отобразить Instant на java.sql.Timestamp, который Slick может использовать изначально.

implicit val instantColumnType: BaseColumnType[Instant] =
    MappedColumnType.base[Instant, Timestamp](
        instant => Timestamp.from(instant),
        ts => ts.toInstant
    )

2) Функции для извлечения года и месяца из вашей метки времени. Здесь я использовал другой подход, чем ваш запрос LIKE. Вы также можете определить отображение из Instant в String и использовать что-то вроде startWith.

val yearFn = SimpleFunction.unary[Instant, Int]("year")
val monthFn = SimpleFunction.unary[Instant, Int]("month")

Тогда вы бы использовали их в getMonthlyOrder, как это

def getMonthlyOrder(year: Int, month: Int): Future[Seq[Order]] = {
    val query = table.filter(_.created.map((created) => yearFn(created) === year && monthFn(created) === month))
    db.run(query.result)
}

Полный код, действительный для Slick 3.1:

import java.sql.Timestamp
import java.time.Instant
import javax.inject.{Inject, Singleton}

import play.api.db.slick.{DatabaseConfigProvider, HasDatabaseConfigProvider}
import slick.driver.JdbcProfile
import slick.lifted.TableQuery

import scala.concurrent.Future

case class Order(id: Int,
                 customerId: Int,
                 amount: Double,
                 created: Option[Instant],
                 updated: Option[Instant])
@Singleton
class Orders @Inject()(val dbConfigProvider: DatabaseConfigProvider) extends HasDatabaseConfigProvider[JdbcProfile] {
    val table = TableQuery[OrderTable]

    import driver.api._

    implicit val instantColumnType: BaseColumnType[Instant] =
        MappedColumnType.base[Instant, Timestamp](
            instant => Timestamp.from(instant),
            ts => ts.toInstant
        )

    val yearFn = SimpleFunction.unary[Instant, Int]("year")
    val monthFn = SimpleFunction.unary[Instant, Int]("month")

    def getMonthlyOrder(year: Int, month: Int): Future[Seq[Order]] = {
        val query = table.filter(_.created.map((created) => yearFn(created) === year && monthFn(created) === month))
        db.run(query.result)
    }

    class OrderTable(tag: Tag) extends Table[Order](tag, "ORDERS") {

        def * = (id, customerId, amount, created, updated) <> ((Order.apply _).tupled, Order.unapply)

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

        def customerId = column[Int]("CUSTOMER_ID")

        def amount = column[Double]("AMOUNT")

        def created = column[Option[Instant]]("CREATED")

        def updated = column[Option[Instant]]("UPDATED")
    }

}
Автор: user3588254 Размещён: 09.08.2016 09:34
Вопросы из категории :
32x32