I use Postgres JSONB columns to store translations for dynamic content of a multi-language site — locales are keys, translated strings are values ({"en": "Hello", "ru": "Привет"}
).
There're some rare cases when I want to ensure that each translation is unique per locale. I know that I can create an index for each locale:
CREATE UNIQUE INDEX ON categories ((title ->> 'en'));
CREATE UNIQUE INDEX ON categories ((title ->> 'ru'));
This solution has one downside that I would need to create a new index for every column which has such constraint if I decide to add a new locale. Is there any way to specify a uniqueness constraint that will hold for every key-value pair of a JSONB object?
EDIT 1 (in response to the Evan's answer). There seems to be some sort of confusion cased by the term "unique/duplicate translation per locale", so I will try to clarify it. "Unique translation per locale" means: for every locale of each record in the table, there is no other record that has exactly the same translation for that locale. "Locale" is the key of the JSONB object that holds translations. "Translation" is the value of the JSONB object.
Here are some examples: the code
INSERT INTO categories(title) VALUES
('{"en": "Hello"}'),
('{"en": "Hello"}');
should yield a uniqueness constraint violation error because it has duplicate "Hello" translation for the en
locale, while the code
INSERT INTO categories(title) VALUES
('{"en": "Hello"}'),
('{"en": "Hi"}');
should not, because it has different translations for the en
locale.
{"en": "Hello", "ru": "Привет"}
and the other one has a{"en": "Hello", "fr": "Frog Nonsense"}
should the row that only partially overlaps collide or not?title
islocale
->translation
pairs which holds translations of category title in different locales, for example:{"en": "Programming", "ru": "Программирование"}
.