2016-07-18 1 views
1

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

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

Этот запрос отлично работает в Postgres.


Скала код, который я написал для 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?.

+1

ли вы попробовать https://github.com/tminglei/ пятно-страничный? – OlivierBlanvillain

ответ

1

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

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 и использовать что-то вроде startsWith.

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") 
    } 

}