Шаблон db для поиска владельца записи - PullRequest
0 голосов
/ 11 июля 2020

Я ищу шаблон для работы в ситуации, когда запись в таблице может быть связана с 1 и только с одной из нескольких других записей, и мне нужно знать, с какой. Это сложно описать, поэтому я буду использовать пример с клиентом oauth из недавнего проекта.

У клиента есть идентификатор и секрет, и команды или пользователи могут владеть клиентами

clients
client_id|client_secret

user_clients
user_id|client_id

team_clients
team_id|client_id

Проблема вот когда кто-то пытается использовать учетные данные клиента для получения токена доступа, мне нужно знать, принадлежат ли эти учетные данные команде или пользователю. Я не совсем уверен, как лучше с этим справиться, я контролирую базу данных, чтобы можно было вносить изменения.

Некоторые варианты, которые я рассмотрел:

Modify clients and remove user_clients and team clients

clients
client_id|client_secret|team_id(nullable)|user_id(nullable)
Create a client owners table and remove user_clients and team_clients

client_owners
team_id(nullable)|user_id(nullable)|client_id
Adding a type to the clients table and doing 2 queries or a conditional query

clients
client_id|client_secret|type(user or team)

Left joins and filtering/mapping in code.

select * from clients c left join user_clients u ... left join team_clients t ... where c.client_id = ?

Ни один из этих вариантов не кажется прекрасным, поэтому мне интересно, есть ли лучший образец. Это упрощенный пример, иногда эти объекты намного сложнее и имеют гораздо больше возможных взаимосвязей, поэтому запросы могут быть довольно сложными, а также трудными для управления при использовании orm (хотя требование сырого sql для частей системы не является проблема).

Мне бы хотелось услышать, как люди решают эту проблему.

Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 11 июля 2020

Дизайн

То, что вы описываете как отношения 1: n:

  • Один пользователь может владеть несколькими клиентами
  • Одна команда может владеть несколькими клиентами

Итак, первый подход кажется подходящим: таблица client имеет столбец пользователя и столбец клиента.

Теперь вы говорите, что клиент может принадлежать только или пользователю или клиент. Для этого в таблице клиентов должно быть указано ограничение, чтобы гарантировать, что установлен только один из идентификаторов. (И если каждый клиент должен иметь владельца, это ограничение также будет заботиться об этом.)

Некоторые примеры запросов

Если вы хотите получить всех клиентов, принадлежащих пользователям :

select * from clients where user_id is not null;

Если вы хотите знать, принадлежит ли клиент пользователю или группе:

select
  c.*,
  case when user_id is not null then 'user' 
       when team_id is not null then 'team' 
                                else 'none'
  end as owner
from clients c;

Если вам нужна информация о пользователе или команде:

select c.*, coalesce(u.name, t.name) as owner_name
from clients c
left join users u on u.user_id = c.user_id
left join teams t on t.team_id = c.team_id;
0 голосов
/ 11 июля 2020

Идея с левыми соединениями - это то, с чем вы можете go. Оставьте свою таблицу clients только с clientID и присоединитесь к ней слева на user_clients и team_clients.

Вы также можете объединить это с вашим первым вариантом и добавить столбец для user_clientsID и team_clientsID и при добавлении к левому соединению clients.user_clientsID <> 0, которое поможет вам с.

Второй и третий варианты - это то, что я тоже использовал. Второй вариант, возможно, иногда вызывает наибольшую головную боль.

Также вы можете рассмотреть вариант создания таблицы представления со всей необходимой информацией

...