Slick:过滤所有joda DateTime日期等于今天的记录

时间:2014-01-25 12:16:12

标签: scala jodatime slick

实现它的一种方法是:

val now = DateTime.now

val today = now.toLocalDate
val tomorrow = today.plusDays(1)

val startOfToday = today.toDateTimeAtStartOfDay(now.getZone)
val startOfTomorrow = tomorrow.toDateTimeAtStartOfDay(now.getZone)

val todayLogItems = logItems.filter(logItem =>
  logItem.MyDateTime >= startOfToday && logItem.MyDateTime < startOfTomorrow
).list

有没有办法以更简洁的方式编写查询?有点像:

logItems.filter(_.MyDateTime.toDate == DateTime.now.toDate).list

我问这个是因为LINQ to NHibernate是可以实现的(Fetching records by date with only day part comparison using nhibernate)。

2 个答案:

答案 0 :(得分:4)

除非Slick joda映射器增加了对比较的支持,否则你运气不好,除非你自己添加它。为了给它一个镜头,这些可能是有用的指针: * http://slick.typesafe.com/doc/2.0.0/userdefined.html * http://slick.typesafe.com/doc/2.0.0/api/#scala.slick.lifted.ExtensionMethods * https://github.com/slick/slick/blob/2.0.0/src/main/scala/scala/slick/lifted/ExtensionMethods.scala

我创建了一张票,可以在Slick中查看它:https://github.com/slick/slick/issues/627

答案 1 :(得分:2)

通过使用LocalDateTimes而不是直接使用LocalDates,您会感到困惑:

val today = LocalDate.now
val todayLogItems = logItems.filter(_.MyDateTime.toLocalDate isEqual today)

<强>更新

这里的问题需要 Major 澄清,Slick只是通过标签顺便提及。

然而...... Slick是这个问题的核心,这取决于filter操作实际上是通过PlainColumnExtensionMethods

进入SQL查询的事实

我对这个库并不是很熟悉,但这肯定意味着你只能被限制在可以在SQL中执行的操作。因为这是一个Column [DateTime],所以你必须将它与另一个DateTime进行比较。

至于LINQ示例,它似乎建议首先获取所有内容然后按照上面的示例继续进行(在Scala中执行比较而不是在SQL中执行比较)。这是一个选项,但我怀疑你不会想要它所带来的性能成本。

更新2 (只是为了澄清)

没有答案。

无法保证您的基础数据库能够在日期和时间戳之间进行相等性检查,因此不能依赖现有的这种能力。

你被困在一块岩石和一块坚硬的地方之间。您可以像现在一样在时间戳之间进行范围检查,也可以从查询中提取所有内容并在Scala中对其进行过滤 - 这可能会带来很高的性能成本。

最终更新

要参考您引用的Linq / NHibernate问题,以下是一些引用:

  • 您还可以使用Criteria中的日期函数,通过SqlFunction
  • 这取决于LINQ提供商
  • 我不确定NHibernate LINQ提供程序是否支持...

所以答案似乎是:

  • 依靠NHibernate将日期强制逻辑推送到数据库中,如果不可能,可能会默默地削弱性能(通过获取所有记录并在本地过滤)
  • 依靠您编写自定义SQL逻辑

最好的情况是NHibernate可以将日期/时间戳比较转换为时间戳范围检查。做这样的事情是关于Slick(和slick-joda-mapper)如何处理比较的一个非常深刻的问题,你在过滤器中使用它的事实是偶然的。

您需要一个极其引人注目的用例来自行编写这样的功能,因为存在创建复杂错误的风险。你会好起来的:

  • 将列拆分为单独的日期/时间列
  • 将日期添加为计算列(可能在视图中)
  • 使用自定义SQL(或存储过程)进行查询
  • 坚持范围检查
  • 使用辅助功能

如果是助手:

def equalsDate(dt: LocalDate) = {
  val start = dt.toDateTimeAtStartOfDay()
  val end = dt.plusDays(1).toDateTimeAtStartOfDay()
  (col: Column[DateTime]) => {
    col >= start && col < end
  }
}

val isToday = equalsDate(LocalDate.now)
val todayLogItems = logItems.filter(x => isToday(x.MyDateTime))