【问题标题】:How to compare DateTime objects in Ecto query where clause?如何比较 Ecto 查询 where 子句中的 DateTime 对象?
【发布时间】:2020-08-16 19:16:29
【问题描述】:

我有一个查询,我想在未来获取所有记录。

  def get_scheduled_notification_pushes_from_date(date\\DateTime.utc_now()) do                                                                         
    query = from s in ScheduledPush,                                                                                                                   
      where: s.status not in ["completed", "cancelled"] and s.utc_schedule_time >= ^date                                                               
                                                                                                                                                       
    Repo.all(query)                                                                                                                                    
  end    

我认为这可能会被转换或转换为 postgres - 但它一定在做一些奇怪的事情。

我也尝试比较 ~U[] 对象.. 但这是个坏主意...

iex(37)> ~U[2020-08-15 20:39:00.000000Z] >= ~U[2020-08-15 20:36:10.367654Z]

warning: invalid comparison with struct literal ~U"2020-08-15 20:39:00.000000Z". Comparison operators (>, <, >=, <=) perform structural and not semantic comparison. Comparing with a struct literal is unlikely to give a meaningful result. Modules typically define a compare/2 function that can be used for semantic comparison

false

如何使用 Ecto 查找基于 DateTime.utc_now() 之前的值的记录?

utc_schedule_time 的类型是 utc_datetime_usec

【问题讨论】:

    标签: postgresql elixir ecto


    【解决方案1】:

    ==== 解决方案 - 问题已解决 - 任何想法为什么? ======

    我认为给我带来问题的原始查询是:

    query = from s in ScheduledPush,                                                                                                                       
          where: s.utc_schedule_time > ^date and s.status not in ["completed", "cancelled"]
    

    没有意识到 Ecto 会适当地转换日期类型以与 postgres/SQL 很好地配合我去终端并做了 ~U[some date]

    我认为这可能是查询中发生的情况,我需要手动转换这些值。

    如果你在一列中有空值并且你尝试和字符串匹配 - 在它不评估记录的情况下,这会如何做一些奇怪的事情?我不知道……我所知道的是,即使所有条件都通过了,我也不再考虑对以该行开头为 null 的字段进行字符串匹配的那一刻。

    我将所有值迁移到“待定”以检查...并且

    瞧:

    [debug] QUERY OK source="scheduled_notification_pushes" db=1.1ms queue=0.8ms idle=9384.5ms
    SELECT s0."id", s0."body", s0."channel_id", s0."timezone", s0."title", s0."user_ids", s0."utc_schedule_time", s0."local_schedule_time", s0."utc_send_time", s0."status", s0."confirmed_send_count", s0."inserted_at", s0."updated_at" FROM "scheduled_notification_pushes" AS s0 WHERE ((s0."utc_schedule_time" > $1) AND NOT (s0."status" IN ('completed','cancelled'))) [~U[2020-08-16 02:01:56Z]]
    
    ["2020-08-19 16:05:00Z pending", "2020-08-19 17:05:00Z pending",
     "2020-08-19 21:05:00Z pending", "2020-08-19 15:05:00Z pending",
     "2020-08-16 02:09:00Z pending", "2020-08-16 04:33:00Z pending",
     "2020-08-16 05:41:00Z pending", "2020-08-19 01:41:00Z pending",
     "2020-08-19 05:41:00Z pending", "2020-08-18 23:41:00Z pending",
     "2020-08-19 00:41:00Z pending"]
    

    我的最终结果是,这可能是架构中的 validate_required 字段,因此查询的结果被删除 - 不,它也不是必需字段。

    更新(answered in elixir forum):

    "WHERE (NOT (s0.status IN ('completed','cancelled'))" ...问题是 NULL - NULL IN ('completed', 'canceled') 不会评估为假 计算结果为 NULL,并且 NOT(NULL) 仍然为 NULL。

    【讨论】:

    • 我喜欢你的解决方案,但你也可以这样做:query = from s in ScheduledPush,其中:s.utc_schedule_time > ^date 和 s.status 不在 ["completed", "cancelled"] 和不是 is_nil(s.status)
    • 是的,你是对的,谢谢。我想消除数据中的歧义,幸运的是,这是我正在创建的表,因此可以设置默认值而不必迁移现有数据。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-24
    相关资源
    最近更新 更多