Как создать индекс на массиве json в postgres? - PullRequest
0 голосов
/ 01 января 2019

У меня в демонстрационной таблице есть поле json под названием 'elements', которое содержит массив 'data', содержащий пары ключ-значение.массив «data» имеет следующую структуру.массив данных может иметь несколько записей json. Я использую postgres версии 9.5

{
    "data": [{
        "ownr": "1",
        "sigUsr": [2],
        "sigStat": "APPR",
        "modifiedOn": 1494229698039,
        "isDel": "false",
        "parentId": "nil",
        "disName": "exmp.json",
        "uniqueId": "d88cb52",
        "usrType": "owner",
        "usrId": "1",
        "createdOn": 1494229698039,
        "obType": "file"
    }]
}

В моем запросе у меня есть несколько фильтров, основанных на obj (например, obj->>usrId, obj->>sigUsr и т. д.), где obj соответствуетjson_array_elements(demo.elements->'data'). Как мне создать индексы btree на фильтрах типа obj->>userId, obj->>sigUsr?Пожалуйста, вернитесь.

С уважением,

1 Ответ

0 голосов
/ 01 января 2019

Во-первых, если тип данных вашего столбца JSON, а не JSONB, вы можете создать индекс только для всего столбца demo.elements.Только ключи JSONB могут иметь индексы для ключей json.

Вы можете изменить тип данных, если в этой таблице укажите JSON.

Затем я изменю вашу ситуацию в тесте.случай следующим образом.

create table demo(
elements jsonb
);
insert into demo values(
'{
    "data": [
        {
            "ownr": "1",
            "sigUsr": [
                2
            ],
            "sigStat": "APPR",
            "modifiedOn": 1494229698039,
            "isDel": "false",
            "parentId": "nil",
            "disName": "exmp.json",
            "uniqueId": "d88cb52",
            "usrType": "owner",
            "usrId": "1",
            "createdOn": 1494229698039,
            "obType": "file"
        }
    ]
}'
);

И запрос, который вы задаете, может быть выполнен следующими способами, как я могу себе представить.

postgres=# -- First possible query
postgres=# select elements->'data'->0->'usrId', elements->'data'->0->'sigUsr' from demo;
 ?column? | ?column? 
----------+----------
 "1"      | [2]
(1 row)

postgres=# -- Second possible query, with jsonb_array_elements()
postgres=# select obj->>'usrId', obj->>'sigUsr' from demo d,  jsonb_array_elements(d.elements->'data') as obj;
 ?column? | ?column? 
----------+----------
 1        | [2]
(1 row)

postgres=# 

Я могу создать индекс только с первым, которыйограниченный вариант использования.вам нужно написать конкретную запись массива в вашем индексе (в данном случае это 0-й элемент).

postgres=# create index ON demo ((elements->'data'->0->'usrId'));
CREATE INDEX
postgres=# 

Я не могу создать индекс для второго подхода, поскольку jsonb_array_elements() возвращает тип setof jsonb.

postgres=# create index ON demo ((jsonb_array_elements(elements->'data')->>'usrId'));
ERROR:  set-returning functions are not allowed in index expressions
LINE 1: create index ON demo ((jsonb_array_elements(elements->'data'...
                               ^
postgres=# 

Я думаю, что вы должны хранить записи sub-json в отдельных строках, а не сохранять их в массиве json.

...