I wondering what will be the right approach to build EAV on jsonb.
I have Attribute -> Values tables as like in standard EAV.
CREATE TA
I do not recommend a separate table for attribute values like we might have done in years gone by. Put a jsonb field right on the appropriate table and call it Attributes. Add a GIN index to it so you can query the values quickly. Or use the other techniques described within.
Read this: https://dba.stackexchange.com/a/174421/7762
The biggest question here is if you intend to pre-define attribute values. If you do, there is an extremely efficient way to store them. If not, then I recommend a standard JSON object.
This gives you the most control, speed, and still provides flexibility.
Create a table Attribute which has these fields:
AttributeID int4 unsigned not null primary keyParentAttributeID int4 unsigned nullName varchar(64) not nullDeleted bool not null default falseParentAttributeIDAttributeID from changingThen in any table you want to attribute, add this field:
AttributeSet" int[] not null defaultintarray extension from https://www.postgresql.org/docs/current/static/intarray.htmlWhat has this accomplished?
You've create a tree of attributes. It might look like this:
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
Say you have a table called Items and on it you've added AttributeSet:
ItemID: 1234
Name: Tee Shirt
AttributeSet: [100, 103, 110, 112]
When translated, this means that it has the Color=Green attribute, and the Size=Medium attribute. 103 and 112 were enough to store that, but sometimes it's nice to be able to say "Show me all items that have any Size defined", that's why 110 was included.
You can make this lightning fast and ultra flexible.
SELECT
"ItemID", "Name"
FROM
"Items"
WHERE "AttributeMap" @> ARRAY[103,112]
Will return all items that have Size=Medium and Color=Green
Or you can use the other operators on https://www.postgresql.org/docs/10/static/functions-array.html to come up with some awesome queries.
This gives you the most speed, control, and is even more flexible. You can flag new attributes for review if needed.
You can use the above technique and just dynamically add values to the Attribute table if they don't exist.
This gives you the most flexibility, but at the expense of control.
In this case just add this to any table:
AttributeMap jsonb not null default '{}'::jsonbWrite code to validate the values against your Attribute table. Have an indicator there if it is a single or multi-value...
Store like this in the AttributeMap field:
{
"Color": "Green",
"Size": "Medium",
"Categories": ["Sports", "Leisure"]
}
Notice that Categories is a multi-attribute. In youe Attribute table you should have a field that is IsMulti bool not null which will allow you to know how to query for it.