Было бы намного эффективнее хранить ваши значения в нормализованной схеме. Тем не менее, вы также можете заставить его работать с вашей текущей настройкой.
Предположения
Предполагая это определение таблицы:
CREATE TABLE tbl (tbl_id int, usr jsonb);
«пользователь» является зарезервированным словом и требует использования двойных кавычек в качестве имени столбца. Не делай этого. Я использую usr
вместо этого.
запрос
Запрос не так тривиален, как (теперь удаленные) комментарии, которые он казал:
SELECT t.tbl_id, obj.val->>'count' AS count
FROM tbl t
JOIN LATERAL jsonb_array_elements(t.usr) obj(val) ON obj.val->>'_id' = '1'
WHERE t.usr @> '[{"_id":"1"}]';
Есть 3 основных шага :
1. Определите подходящие строки дешево
WHERE t.usr @> '[{"_id":"1"}]'
идентифицирует строки с соответствующим объектом в массиве JSON. Выражение может использовать общий индекс GIN для jsonb
столбца или индекс с более специализированным классом операторов jsonb_path_ops
:
CREATE INDEX tbl_usr_gin_idx ON tbl USING gin (usr jsonb_path_ops);
Добавленное WHERE
предложение логически избыточно , но оно требует использования индекса. Выражение в предложении соединения применяет то же условие, но только после удаления массива в каждой строке, соответствующей требованиям. С поддержкой индекса Postgres обрабатывает только те строки, которые содержат квалифицирующий объект для начала. Не имеет большого значения для маленьких таблиц, имеет огромное значение для больших таблиц и только нескольких подходящих строк.
Связанные с:
2. Определите соответствующий объект (ы) в массиве
Unnest с jsonb_array_elements()
. ( unnest()
подходит только для типов массивов Postgres.) Поскольку нас интересует только фактическое сопоставление объектов, немедленно отфильтруйте условие соединения.
Связанные с:
3. Извлечь значение для вложенного ключа 'count'
После квалификации объекты были извлечены, просто: obj.val->>'count'
.
obj(value)
взялся? Это наLATERAL JOIN
,jsonb_array_elements
или где-то еще?