postgresql 用jsonpath表达式比较日期字符串

siv3szwd  于 2023-05-28  发布在  PostgreSQL
关注(0)|答案(2)|浏览(283)

我正在尝试运行以下查询,除非我误解了文档,否则它看起来应该是可能的。

SELECT id, profile
FROM end_user
WHERE profile @? '$.first_segment_exited_at ? (@.datetime() < "2023-05-25".datetime())'::jsonpath;

这是文档,它使我认为我应该能够实现这一点:
string . datetime()→ datetime_type(参见注解)
从字符串转换的日期/时间值
jsonb_path_query('[“2015-8-1”,“2015-08-12”]','$[*]?(@.datetime()<“2015-08-2”.datetime())')→“2015-8-1”
示例配置文件数据,注意日期是有效的ISO格式;

{
  "first_segment_exited_at": "2023-05-22T03:09:37.825Z",
}

下面的查询返回结果,但我希望切换到jsonpath语法,以便利用索引

select id, profile
from end_user
where '2023-05-25'::timestamptz > (profile->>'first_segment_exited_at')::timestamptz

我正在运行Postgres v14。

z9zf31ra

z9zf31ra1#

表列中的JSON日期时间格式非法。这个方法的作用是:

CREATE TABLE end_user (id int, profile jsonb);
INSERT INTO end_user VALUES
  (1, '{"first_segment_exited_at": "2023-05-22T03:09:37.825Z"}')
, (2, '{"first_segment_exited_at": "2023-05-22T03:09:37Z"}')  -- no fractional sec
, (3, '{"first_segment_exited_at": "2023-05-22T03:09:37"}')   -- no trailing "Z", either
;

SELECT *
FROM   end_user
WHERE  profile @? '$.first_segment_exited_at ? (@.datetime() < "2023-05-25".datetime())';

fiddle
第3行是唯一具有法律的格式的。
(The筛选器表达式也需要有效。)
您没有收到错误消息,因为,引用手册:
jsonpath运算符@?@@抑制以下错误:缺少对象字段或数组元素、意外的JSON项类型、日期时间和数值错误。[...]在搜索不同结构的JSON文档集合时,此行为可能会有所帮助。
若要调试输入字符串,请使用不抑制错误的函数进行测试。如jsonb_path_query_first()

SELECT jsonb_path_query_first('{"d": "2023-05-22T03:09:37.1"}', '$.d.datetime()')
ERROR:  datetime format is not recognized: "2023-05-22T03:09:37.1"
HINT:  Use a datetime template argument to specify the input data format.

但这只会飞:

SELECT jsonb_path_query_first('{"d": "2023-05-22T03:09:37"}', '$.d.datetime()')

此外,您可以为.datetime()方法提供模板模式,如Laurenz在他的补充回答中所演示的。(前方还有更多障碍……)

kcrjzv8t

kcrjzv8t2#

问题是您的日期不是datetime()识别的格式,您必须指定一个带有datetime()的模板字符串。使用以下jsonpath

'$.first_segment_exited_at ? (@.datetime("YYYY-MM-DD\"T\"HH24:MI:SS.MS\"Z\"") < "2023-05-25".datetime())'::jsonpath

我不得不使用(我相信没有文档)PostgreSQL扩展的双引号文本格式字符串来匹配字符串中的TZ

相关问题