Owens

Owens

Unique Index/Constraint allow duplicates ONLY when ALL references are null

Hello all,

I’m creating a chat app that automatically creates chats between different groups of people as well as individuals. I want to make sure it doesn’t create any duplicates for the chats between these groups, but also allows for individual chats (private) where all the references are nil.

create unique_index(:chats,
  [:parent_organization_id, :organization_id, :cohort_id, :team_id])

My understanding is that if any reference above is nil, postgres will allow duplicates.

To fix this, @LostKobrakai recommends here to create indexes with coalesce’d values like so:

execute( "create unique index INDEX_NAME on TABLE
  (
    coalesce(parent_organization_id, ''),
    coalesce(organization_id, ''),
    coalesce(cohort_id, ''),
    coalesce(team_id, '')
  );
")

But the problem is I need to ALLOW duplicates when all the references are nil (which they will be for individual chats between users).

In other words,

I need to PREVENT duplicates for these

parent_organization_id: 1, organization_id: nil, cohort_id: nil, team_id: nil
parent_organization_id: 1, organization_id: 1,   cohort_id: nil, team_id: nil
parent_organization_id: 1, organization_id: 1,   cohort_id: 1,   team_id: nil

parent_organization_id: nil, organization_id: 1,   cohort_id: nil, team_id: nil
parent_organization_id: nil, organization_id: 1,   cohort_id: 1,   team_id: nil

and ALLOW duplicates for these

parent_organization_id: nil, organization_id: nil, cohort_id: nil, team_id: nil

Appreciate any thoughts. Thank you.

Marked As Solved

Owens

Owens

It worked after changing

coalesce(parent_organization_id, '')

to

coalesce(parent_organization_id, -1)

Full code:

def change do
    drop unique_index(:chats, [:parent_organization_id, :organization_id, :cohort_id, :team_id])

    execute( "create unique index chats_parent_organization_id_organization_id_cohort_id_team_id_index on chats
        (
            coalesce(parent_organization_id, -1),
            coalesce(organization_id, -1),
            coalesce(cohort_id, -1),
            coalesce(team_id, -1)
        ) where type != 'direct'
    ")
end

Also Liked

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

@Owens One certainly easy option here is an additional direct or individual column that you set to true, and then you can just WHERE individual == false on your unique index. This does mean you have to set that value, but OTOH it also makes it much more explicit, whereas the version that relies on N columns being nil feels very implicit.

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe
xecute( "create unique index INDEX_NAME on TABLE
  (
    coalesce(parent_organization_id, ''),
    coalesce(organization_id, ''),
    coalesce(cohort_id, ''),
    coalesce(team_id, '')
  ) where individual == false
")

This marks what is called a “partial index” where the index only applies to the rows where the condition is true.

Where Next?

Popular in Questions Top

JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
dotdotdotPaul
Okay, I'm having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I'm sure I'...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
Werner
Hi, I’m using Ubuntu 18.04 and after updating to OTP-24.0 yesterday i have this warning when I run “mix local.hex”: 14:57:30.512 [warn] ...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
chewm
Hi guys, nice to meet you to the whole forum, I’m new here, I’m trying to configure visual studio code for elixir, right now the intellis...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New

Other popular topics Top

shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
Tee
can someone please explain to me how Enum.reduce works with maps
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
Jim
As a follow up to my earlier question: I have the code compiling and running but not getting a successful login from the rest server. ...
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
magnetic
Hey :wave:t3: Elixir community, I’ve been learning Elixir, and working on some side projects. My editor of choice is VSCode, and althoug...
New

We're in Beta

About us Mission Statement