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

时间:2018-08-01 20:05:28

标签: ruby-on-rails postgresql ruby-on-rails-5 rails-activerecord

就像标题一样,如何在查询中包含日期范围?

例如,假设我有一个名为VisitToGrandma的模型,并且有一个名为visit_date的字段。现在,我想查找上个月发生的所有对祖母的拜访。

这是我正在尝试的:

VisitToGrandma.where("? @> visit_date", (1.month.ago..Time.now))

但是,这会产生查询:

  

选择“ visits_to_grandmas”。*从“ visits_to_grandmas”位置('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或其他一些运算符来执行此操作,而无需使用实际的日期范围,但这不是我想要的在问。

编辑以指出此问题与the other question有何不同:

该问题仅与查找范围内的日期有关,我的问题是询问如何实际对范围对象进行参数化,以便可以使用所有postgresql的daterange运算符。

2 个答案:

答案 0 :(得分:1)

似乎您需要滥用一些where占位符才能使用ActiveRecord完成此操作

VisitToGrandma.where(
  ":range::daterange @> date",
  range: '[2011-01-01,2011-03-01)'
)

请注意该范围内的符号[),有关Postgres文档的更多信息 https://www.postgresql.org/docs/current/static/rangetypes.html#RANGETYPES-IO

答案 1 :(得分:1)

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

您可以通过半手动生成所需范围的字符串表示来解决此问题:

ActiveRecord::Base.connection.type_cast(1.month.ago.to_date .. Time.now.to_date)

不是#to_date调用来获取日期而不是时间戳。您还可以说:

today = Date.today
ActiveRecord::Base.connection.type_cast(today.months_ago(1) .. today)

与您的查询混合:

today = Date.today
VisitToGrandma.where(
  '? @> visit_date',
  VisitToGrandma.connection.type_cast(today.months_ago(1) .. today)
)

根据上下文,您可能更容易/更干净地访问connection。您可能想要包括一个类型转换,只是为了确保没有任何误解:

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