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
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
@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
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.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









