1

I have user table with id as GUID and I want to create group table for users.

Constraint: group table row should be unique for a set of users?

Meaning if I want to create a new group previously I need to check if such a group already exists, meaning I need to check if my array of user GUIDs already exists in group table.

Here is a schema approximation where I use Array of UUID and Unique constraint:

CREATE TABLE user (
   id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
   ...
)

CREATE TABLE group (
   ...
   users_array UUID[] UNIQUE,
   ...
)

When I create a new group I check if there is a group for the current sorted set of users, if there is no such group I create a new record if there is then I just retrieve the existing group.

Do you think UUID[] UNIQUE is the best solution for search and what would be the alternatives?

2
  • 1
    Normalize your data model. Then it gets as simple as creating a unique index Commented Nov 24, 2020 at 7:45
  • @a_horse_with_no_name Could you elaborate on this please? You are suggesting to introduce a user_group table that will connect user to group and avoid using array field, correct? So you can select group by JOINing with user_table and order records by user_id, but how would you index and put UNIQUE constraint on it? Thanks Commented Nov 24, 2020 at 7:58

2 Answers 2

2

I'm not sure this is the best representation of the data. But you want a unique condition on an array. The problem is that arrays in different orders are not the same.

And, unfortunately, Postgres does not have an "array sort" function. Of course, this is easy enough to do in SQL using array_agg() and unnest(). But those are not allowed in an index definition

But user-defined functions are. So, start with:

create function array_sort(anyarray) returns anyarray as $$
    select array_agg(distinct n order by n)
    from unnest($1) as t(n);
$$ language sql immutable;

Then you can use this in a unique constraint:

create unique constraint unq_groups_users on groups(array_sort(users));
Sign up to request clarification or add additional context in comments.

1 Comment

good point. I am planing to sort array in the backend. I wonder more about how would you handle such situation, what data model alternative you can suggest. Thanks.
1
+50

You cold normalize that, making another table like an user_group (you already discussed about it)

But to make it unique you could use a funcion or a procedure to create a new user_group, this is not the best solution to create a new user_group but it makes better to handle these information after it's created.

It depends on how often you create vs manipulate those data.

2 Comments

Good point! Thank you @Rodrigo. I decided to go with my initial approach, having a sorted array with UNIQUE constraint + I would still probably have user_group table with data duplication, but I think this can justify the simplicity and possibly the speed of this type of design and I will avoid introducing DB function/procedure as another layer of business logic. Makes sense, what do you think?
Yes, its good to avoid as much as possible to use functions or procedures, but in some particular times it's better to use it, because backend can make a mess in your database like this case. You must always think what's the better solution for your case and sometimes you can't avoid drawbacks than you choose the lesser evil. Finaly, if your approach has no inconsistency or other huge negative impact there is no problem using it even with data duplication.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.