Scala Slick:筛选joda DateTime日期等于今天的所有记录

Scala Slick:筛选joda DateTime日期等于今天的所有记录,scala,jodatime,slick,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 = l

实现这一目标的一种方法是:

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

我这样问是因为在LINQ to NHibernate中,这是可以实现的()。

使用LocalDateTimes而不是直接使用LocalDates会让事情变得混乱:

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

这里需要对这个问题做一个主要的澄清,Slick只是顺便提到的,只是作为一个标签

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

我对该库不太熟悉,但这肯定意味着您仅限于可以在SQL中执行的操作。由于这是一列[DateTime],因此必须将其与另一个DateTime进行比较

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

更新2(只是澄清一下)

没有答案

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

你被困在岩石和坚硬的地方之间。要么像现在一样在时间戳之间进行范围检查,要么从查询中提取所有内容并在Scala中进行过滤——这可能会带来沉重的性能代价

最终更新

关于你提到的Linq/NHibernate问题,这里有几句话:

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

  • 依靠NHibernate将日期强制逻辑推送到数据库中,如果不可能,可能会默默地削弱性能(通过获取所有记录并在本地进行过滤)
  • 依赖您编写自定义SQL逻辑
最好的情况是NHibernate可以将日期/时间戳比较转换为时间戳范围检查。这样做是一个相当深刻的问题,关于Slick(和Slick joda mapper)如何处理比较,在过滤器中使用它是偶然的

考虑到创建复杂bug的风险,您需要一个非常引人注目的用例来自己编写这样的特性。你最好是:

  • 将列拆分为单独的日期/时间列
  • 将日期添加为计算列(可能在视图中)
  • 使用自定义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))
def equalsDate(dt:LocalDate)={
val start=dt.toDateTimeAtStartOfDay()
val end=dt.plusDays(1).toDateTimeAtStartOfDay()
(列[DateTime])=>{
列>=开始和列<结束
}
}
val isToday=equalsDate(LocalDate.now)
val todayLogItems=logItems.filter(x=>isToday(x.MyDateTime))

除非精巧的joda mapper添加了对比较的支持,否则除非您自己添加,否则您的运气就不好了。为了给它一个机会,这些可能是有用的提示: * * *


我创建了一个ticket,以便在某个时候在Slick中查看它:

这不起作用,因为
.MyDateTime
没有
toLocalDate
方法,因为它属于
列[Imports.DateTime]
。我正在导入
导入com.github.tototoshi.slick.H2JodaSupport.\u
来自
https://github.com/tototoshi/slick-joda-mapper
,这使得它可以像我的示例中使用的那样工作。但是访问MyDateTime的成员是不起作用的。将
slick
作为标记和问题中的第二个示例(这不起作用,但如果它只在内存中运行就会起作用)足以清楚地说明问题上下文是什么。对不起,我不能投票或接受你的
答案,因为它不能回答问题。如果没有答案,就没有问题。仅仅为了在内存中查询而从数据库中检索所有数据并不是一个解决方案,因为可以使用问题中提到的方法在数据库中进行查询,而不会受到任何惩罚。数据库只需要支持时间戳比较,LINQ可以在不考虑数据库的情况下执行该查询,这证明了Slick也可以这样做。无论如何,+1表示感谢。别忘了用===代替==
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))