如何在 rails (postgres) 查询中参数化日期范围?

Ste*_*ies 2 postgresql ruby-on-rails rails-activerecord ruby-on-rails-5

就像标题所问的那样,如何在查询中包含日期范围?

例如,假设我有一个名为的模型VisitToGrandma,它有一个名为visit_date. 现在,我想找到上个月发生的所有对祖母的访问。

这是我正在尝试的:

VisitToGrandma.where("? @> visit_date", (1.month.ago..Time.now))
Run Code Online (Sandbox Code Playgroud)

但是,这会产生查询:

SELECT "visits_to_grandmas".* FROM "visits_to_grandmas" WHERE ('2018-07-01','2018-07-02','2018-07-03','2018-07-04','2018-07-05 ','2018-07-06','2018-07-07','2018-07-08','2018-07-09','2018-07-10','2018-07-11', '2018-07-12'、'2018-07-13'、'2018-07-14'、'2018-07-15'、'2018-07-16'、'2018-07-17'、'2018 -07-18','2018-07-19','2018-07-20','2018-07-21','2018-07-22','2018-07-23','2018-07 -24'、'2018-07-25'、'2018-07-26'、'2018-07-27'、'2018-07-28'、'2018-07-29'、'2018-07-30 ','2018-07-31','2018-08-01'@>visit_date)

参数化这个的正确方法是什么?

是的,我知道对于这个虚构的例子,我可以只使用开始和结束日期并使用BETWEEN或其他一些运算符来执行此操作,而无需使用实际日期范围,但这不是我要问的。

编辑以指出这个问题与另一个问题的不同之处:

这个问题只是关于在一个范围内找到一个日期,我的问题是询问如何实际参数化一个范围对象,以便可以使用所有 postgresql 的日期范围运算符。

mu *_*ort 5

正如我最近在另一个PostgreSQL/range/ActiveRecord回答中提到的,AR 与 PostgreSQL 的范围类型的集成是有限的。

您可以通过半手动生成您想要的范围的字符串表示来解决这个问题:

ActiveRecord::Base.connection.type_cast(1.month.ago.to_date .. Time.now.to_date)
Run Code Online (Sandbox Code Playgroud)

不是#to_date获取日期而不是时间戳的调用。你也可以说:

today = Date.today
ActiveRecord::Base.connection.type_cast(today.months_ago(1) .. today)
Run Code Online (Sandbox Code Playgroud)

将其与您的查询混合:

today = Date.today
VisitToGrandma.where(
  '? @> visit_date',
  VisitToGrandma.connection.type_cast(today.months_ago(1) .. today)
)
Run Code Online (Sandbox Code Playgroud)

根据上下文,您可能可以更轻松/更清晰地访问connection. 您可能想要包含一个类型转换,以确保没有任何误解:

today = Date.today
VisitToGrandma.where(
  '?::daterange @> visit_date',
  VisitToGrandma.connection.type_cast(today.months_ago(1) .. today)
)
Run Code Online (Sandbox Code Playgroud)

  • 使用`connection.type_cast` 让它开心。谢谢。:) (2认同)