无法在带有日期的jsonb字段上创建索引

时间:2019-11-15 12:54:30

标签: postgresql jsonb database-indexes

我在表中有一个jsonb列event。我正在尝试创建索引

CREATE INDEX ON table(((events->'START'->> 'date')::timestamp AT TIME ZONE 'PST'));

但是它抛出错误functions in index expression must be marked IMMUTABLE

在传递了时区之后,它应该保持不变,但是我不确定为什么它仍然会引发错误。

2 个答案:

答案 0 :(得分:1)

强制转换为timestamp是您的问题。它不是IMMUTABLE,因为使用的函数接受now之类的参数。

如果确定您的数据仅包含常规时间戳记且不包含此类值,则可以定义自己的IMMUTABLE LANGUAGE sql函数来包装类型转换。

您可以在查询中使用此类功能并将其编入索引。如果存在确实不是强制转换的值,则索引将被破坏。

答案 1 :(得分:0)

我正在使用自己的方法来扩大Laurenz Albe的回答,以便能够发布代码。

假设您有一个表mytable和JSONB字段thedata,其中包含类似{ "datetime": "2020-03-21T33:44:55.193843281Z ", ... }的数据:

-- Create immutable UTC parsing function, see:
-- * https://stackoverflow.com/questions/58877503/cant-create-an-index-on-a-jsonb-field-with-date
-- * https://stackoverflow.com/questions/5973030/error-functions-in-index-expression-must-be-marked-immutable-in-postgres
-- It parses dates of format:
--     YYYY-MM-DDTHH:MM:SSZ
-- (with a 'T' between date and time, and a 'Z' at the end) for example:
--     2020-03-21T33:44:55Z
--     2020-03-21T33:44:55.193843281Z

CREATE OR REPLACE FUNCTION utc_to_timestamp(some_time text)
  RETURNS timestamp with time zone
AS
$BODY$
    select to_timestamp($1, 'YYYY-MM-DD"T"HH24:MI:SS"Z"');
$BODY$
LANGUAGE sql
IMMUTABLE;

-- Define the index:
CREATE INDEX mytable_expr_datetime on mytable (utc_to_timestamp(the_data ->> 'datetime'));

因此,对于问题中的表/字段名称,必须将the_data ->> 'datetime'替换为events->'START'->> 'date',将mytable替换为events