PostgreSQL / JSON ба JSONB өгөгдөл

JSON ба JSONB өгөгдөл

Зарим өгөгдлийн бүтэц урьдчилан тодорхойгүй байдаг — жишээлбэл бүтээгдэхүүний нэмэлт шинж чанар, хэрэглэгчийн тохиргоо, гадаад API-аас ирсэн өгөгдөл. Эдгээрт тусдаа хүснэгт үүсгэхийн оронд PostgreSQL-н JSON эсвэл JSONB төрлийг ашиглаж болно. Энэ нь SQL-н хатуу бүтэц болон MongoDB-г хэрэглэсэн мэт уян хатан байдлыг хослуулдаг.

JSON vs JSONB — ялгаа

| | JSON | JSONB | |---|---|---| | Хадгалалт | Текст хэлбэрээр, дарааллыг хадгална | Хоёртын форматаар, задалсан | | Индекс | ❌ боломжгүй | ✅ GIN индекс | | Хурд (унших) | Удаан (дахин задлах) | Хурдан | | Хурд (бичих) | Хурдан | Арай удаан | | Давхардсан түлхүүр | Хадгална | Сүүлчийнхийг авна |

Ихэнх тохиолдолд JSONB сонгох нь зөв — индекс тавьж болдог, хурдан уншдаг.

sql
CREATE TABLE products (
    id          SERIAL PRIMARY KEY,
    name        TEXT NOT NULL,
    price       NUMERIC NOT NULL,
    attributes  JSONB          -- уян хатан шинж чанарууд
);

INSERT INTO products (name, price, attributes) VALUES
    ('Утас Samsung',  850000, '{"өнгө": "хар", "RAM": 8, "хадгалалт": 128, "5G": true}'),
    ('Утас iPhone',  1200000, '{"өнгө": "цагаан", "RAM": 6, "хадгалалт": 256, "5G": true}'),
    ('Чихэвч Sony',   95000, '{"өнгө": "хар", "утасгүй": true, "цагийн_хугацаа": 30}'),
    ('Гар чийдэн',    12000, '{"гэрэлтэх_хугацаа": 8, "батарей": "AAA"}');

JSON өгөгдлийг унших

PostgreSQL нь JSON утга унших хэд хэдэн оператор санал болгодог:

sql
-- -> оператор: JSON утга буцаана (JSON хэлбэрээр)
SELECT name, attributes -> 'өнгө' AS өнгө
FROM products;
-- Үр дүн: "хар", "цагаан" (хашилттай)

-- ->> оператор: TEXT утга буцаана
SELECT name, attributes ->> 'өнгө' AS өнгө
FROM products;
-- Үр дүн: хар, цагаан (хашилтгүй)

-- Тоон утгыг буцаах
SELECT name, (attributes ->> 'RAM')::INT AS ram_gb
FROM products
WHERE attributes ? 'RAM'
ORDER BY ram_gb DESC;
sql
-- WHERE дотор JSON талбараар шүүх
SELECT name, price
FROM products
WHERE attributes ->> 'өнгө' = 'хар';

-- Тодорхой түлхүүр байгаа эсэхийг шалгах (? оператор)
SELECT name FROM products WHERE attributes ? '5G';

-- Олон түлхүүр байгаа эсэхийг шалгах (?& оператор)
SELECT name FROM products WHERE attributes ?& ARRAY['5G', 'RAM'];

JSON өгөгдлийг шинэчлэх

jsonb_set() функцоор JSONB утгыг шинэчилж болно:

sql
-- Нэг талбарыг шинэчлэх
UPDATE products
SET attributes = jsonb_set(attributes, '{өнгө}', '"улаан"')
WHERE name = 'Гар чийдэн';

-- Шинэ талбар нэмэх
UPDATE products
SET attributes = attributes || '{"баталгаат_хугацаа": 12}'
WHERE name = 'Чихэвч Sony';

-- Талбар устгах (- оператор)
UPDATE products
SET attributes = attributes - 'батарей'
WHERE name = 'Гар чийдэн';

GIN индекс — JSONB хайлтыг хурдасгах

JSONB талбарт GIN индекс тавьснаар их хэмжээний өгөгдөлд хайлт хурдасна:

sql
-- Бүх JSONB түлхүүр болон утгад GIN индекс
CREATE INDEX idx_products_attributes
    ON products USING GIN (attributes);

-- Одоо энэ хайлт маш хурдан болно
SELECT name FROM products
WHERE attributes @> '{"өнгө": "хар"}';
-- @> оператор: зүүн тал нь баруун талыг "агуулж байна уу?" гэдгийг шалгана

JSON хэлбэртэй гаралт

Хүснэгтийн мөрийг JSON болгон буцаах:

sql
-- Мөрийг JSON болгох
SELECT ROW_TO_JSON(p) FROM products p WHERE id = 1;

-- Бүх мөрийг JSON массив болгох
SELECT JSON_AGG(
    JSON_BUILD_OBJECT(
        'нэр', name,
        'үнэ', price,
        'өнгө', attributes ->> 'өнгө'
    )
) AS бараанууд
FROM products
WHERE attributes ? 'өнгө';

Дараагийн хичээлд:

PostgreSQL-д нэг талбарт олон утга хадгалах массив өгөгдлийн төрлийг сурна — тэмдэгт, тоо, огноо бүхий массивыг үүсгэж, хайж, шинэчлэх аргуудыг авч үзнэ.