【问题标题】:Can't create an index on a jsonb field with date无法在带有日期的 jsonb 字段上创建索引
【发布时间】:2019-11-15 12:54:30
【问题描述】:
我在表中有一个 jsonb 列 event。我正在尝试创建索引
CREATE INDEX ON table(((events->'START'->> 'date')::timestamp AT TIME ZONE 'PST'));
但它抛出错误functions in index expression must be marked IMMUTABLE
在传递一个时区后,它应该使其不可变,但我不确定为什么它仍然会抛出错误。
【问题讨论】:
标签:
postgresql
jsonb
database-indexes
【解决方案1】:
timestamp 的演员表是你的问题。不是IMMUTABLE,因为使用的函数接受now 之类的参数。
如果您确定您的数据仅包含常规时间戳而不包含此类值,您可以定义自己的 IMMUTABLE LANGUAGE sql 函数来包装类型转换。
您可以在查询中使用这样的函数并为其编制索引。如果某些值的强制转换确实不是不可变的,那么您的索引将会损坏。
【解决方案2】:
用我自己的增强 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。