Ant*_*nio 10 postgresql index order-by array json
我在 PostgreSQL 中有一个包含一些数据的表:
create table t2 (
key jsonb,
value jsonb
);
INSERT INTO t2(key, value)
VALUES
('1', '"test 1"')
,('2', '"test 2"')
,('3', '"test 3"')
,('[]', '"test 4"')
,('[1]', '"test 5"')
,('[2]', '"test 6"')
,('[3]', '"test 7"')
,('[1, 2]', '"test 8"')
,('[1, 2, 3]', '"test 9"')
,('[1, 3]', '"test 10"')
,('[1,2,4]', '"test 11"')
,('[1, 2,4]', '"test 12"')
,('[1,3,13]', '"test 13"')
,('[1, 2, 15]', '"test 15"');
Run Code Online (Sandbox Code Playgroud)
我尝试像这样对这些行进行排序:
SELECT key FROM t2 order by key;
Run Code Online (Sandbox Code Playgroud)
结果是:
[]
1
2
3
[1]
[2] <==
[3] <==
[1, 2]
[1, 3] <==
[1, 2, 3]
[1, 2, 4]
[1, 2, 4]
[1, 2, 15]
[1, 3, 13]
Run Code Online (Sandbox Code Playgroud)
但我需要的是:
[]
1
2
3
[1]
[1, 2]
[1, 2, 3]
[1, 2, 4]
[1, 2, 4]
[1, 2, 15]
[1, 3] <==
[1, 3, 13]
[2] <==
[3] <==
Run Code Online (Sandbox Code Playgroud)
有没有办法实现它?
首先,您的问题以及您的列名"key"具有误导性。列键不包含任何 JSON键,只有值。否则我们可以使用该函数jsonb_object_keys(jsonb)来提取键,但事实并非如此。
假设您的所有 JSON 数组都是空的或保存整数,如图所示。标量值(非数组)也是整数。
您的基本排序顺序适用于 Postgres integer(或numeric)数组。我使用这个小辅助函数将jsonb数组转换为 Postgres int[]:
CREATE OR REPLACE FUNCTION jsonb_arr2int_arr(_js jsonb)
RETURNS int[] LANGUAGE sql IMMUTABLE AS
'SELECT ARRAY(SELECT j::int FROM jsonb_array_elements_text(_js) j)';
Run Code Online (Sandbox Code Playgroud)
解释:
然后添加jsonb_typeof(jsonb)到:
SELECT key
FROM t2
ORDER BY key <> '[]' -- special case for empty array
, jsonb_typeof(key) DESC -- 'number' before 'array'
, CASE jsonb_typeof(key) -- sort arrays as converted int[]
WHEN 'array' THEN jsonb_arr2int_arr(key)
WHEN 'number' THEN ARRAY[key::text::int]
END;
Run Code Online (Sandbox Code Playgroud)
准确地产生所需的结果。
基准的
btree排序jsonb很少引起人们的兴趣,但为了完整性,它是:
Object > Array > Boolean > Number > String > Null
Object with n pairs > object with n - 1 pairs
Array with n elements > array with n - 1 elements具有相同对数的对象按以下顺序进行比较:
Run Code Online (Sandbox Code Playgroud)key-1, value-1, key-2 ...请注意,对象键按其存储顺序进行比较;特别是,由于较短的密钥存储在较长的密钥之前,这可能会导致可能不直观的结果,例如:
Run Code Online (Sandbox Code Playgroud){ "aa": 1, "c": 1} > {"b": 1, "d": 1}类似地,元素数量相等的数组按以下顺序进行比较:
Run Code Online (Sandbox Code Playgroud)element-1, element-2 ...
大胆强调我的。
这就是为什么jsonb '[2]' < jsonb '[1, 2]'。
但是 Postgres 数组只是逐个元素排序:'{2}'::int[] > '{1, 2}'- 正是您要查找的内容。
| 归档时间: |
|
| 查看次数: |
10133 次 |
| 最近记录: |