Набагато ефективніше було б зберігати свої значення в нормалізованій схемі. Однак, ви також можете змусити це працювати з вашим поточним налаштуванням.
Припущення
Припускаючи це визначення таблиці:
CREATE TABLE tbl (tbl_id int, usr jsonb);
"user" - це зарезервоване слово, і воно потребує подвійного цитування, щоб використовуватись як назва стовпця. Не робіть цього. Я використовую 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"}]';
Є три основні етапи :
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. Визначте відповідні об’єкти (масиви) у масиві
Нечесно з jsonb_array_elements()
. ( unnest()
добре лише для типів масивів Postgres.) Оскільки нас цікавлять лише фактично відповідні об’єкти, фільтруйте в умові приєднання відразу.
Пов'язані:
3. Значення вилучення для вкладеного ключа 'count'
Після кваліфікації об'єкти були вилучені, просто: obj.val->>'count'
.
obj(value)
? Це наLATERAL JOIN
,jsonb_array_elements
чи десь ще?