PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Търсите правилна EAV структура, базирана на jsonb

Цел:Искате да съхраните атрибут, свързан с даден обект.

Не препоръчвам отделна таблица за стойностите на атрибутите, както може би сме правили в миналите години. Поставете jsonb поле вдясно в съответната таблица и го наречете Attributes . Добавете GIN индексирайте го, за да можете бързо да търсите стойностите. Или използвайте другите техники, описани в рамките.

Прочетете това:https://dba.stackexchange.com/a/174421/7762

Най-големият въпрос тук е дали възнамерявате да дефинирате предварително стойности на атрибути. Ако го направите, има изключително ефективен начин да ги съхранявате. Ако не, тогава препоръчвам стандартен JSON обект.

Ако можете предварително да дефинирате имената И стойностите на вашите атрибути:

Това ви дава най-голям контрол, скорост и все още осигурява гъвкавост.

Създайте таблица Attribute който има следните полета:

  • AttributeID int4 unsigned not null primary key
  • ParentAttributeID int4 unsigned null
  • Name varchar(64) not null
  • Deleted bool not null default false
  • Добавяне на индекс към ParentAttributeID
  • Добавете тригер за предотвратяване на AttributeID от промяна
  • Добавете правило за изтриване, вместо това задайте Deleted=True

След това във всяка таблица, която искате да приписвате, добавете това поле:

Какво постигна това?

Създадохте дърво от атрибути. Може да изглежда така:

ID   Parent  Name
----------------------------
100  NULL    Color
101  100       Blue
102  100       Red
103  100       Green
110  NULL    Size
111  110       Large
112  110       Medium 
113  110       Small

Да кажем, че имате таблица, наречена Items и към него сте добавили AttributeSet :

      ItemID: 1234
        Name: Tee Shirt
AttributeSet: [100, 103, 110, 112]

При превод това означава, че има Color=Green атрибут и Size=Medium атрибут. 103 и 112 бяха достатъчни, за да съхраните това, но понякога е хубаво да можете да кажете „Покажи ми всички елементи, които имат определен размер“, затова беше включен 110.

Можете да направите това светкавично бързо и изключително гъвкаво.

SELECT
  "ItemID", "Name"
FROM
  "Items"
WHERE "AttributeMap" @> ARRAY[103,112]

Ще върне всички елементи, които имат Size=Medium и Color=Green

Или можете да използвате другите оператори на https://www.postgresql .org/docs/10/static/functions-array.html за да излезете с някои страхотни заявки.

Когато не знаете стойностите на атрибута, но наборът е малък:

Това ви дава най-голяма скорост, контрол и е още по-гъвкаво. Можете да маркирате нови атрибути за преглед, ако е необходимо.

Можете да използвате горната техника и просто динамично да добавяте стойности към Attribute таблица, ако не съществуват.

Когато не знаете стойностите на атрибутите и стойностите са различни

Това ви дава най-голяма гъвкавост, но за сметка на контрола.

В този случай просто добавете това към всяка таблица:

  • AttributeMap jsonb not null default '{}'::jsonb
  • Добавете GIN индекс към това поле

Напишете код, за да потвърдите стойностите спрямо вашия Attribute маса. Имайте индикатор там, ако е с една или няколко стойности...

Съхранявайте по този начин в AttributeMap поле:

{
    "Color": "Green", 
    "Size": "Medium", 
    "Categories": ["Sports", "Leisure"]
}

Забележете, че Categories е мулти-атрибут. Във вашия Attribute трябва да имате поле, което е IsMulti bool not null което ще ви позволи да знаете как да го търсите.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Присъединете се към един към много и извлечете един резултат

  2. Генерирайте ERD за съществуваща база данни

  3. regexp_matches по-добър начин да се отървете от връщането на къдрави скоби

  4. Docker postgres не изпълнява init файл в docker-entrypoint-initdb.d

  5. Как да изберете редове, където комбинация от 2 колони е една и съща