Mysql

類似 Twitter 的應用程序中的匿名和公共使用者表設計

  • January 25, 2021

我有架構設計問題,我不能 100% 確定我的假設是否正確。

所以要求是:

  1. 我需要有 2 種不同類型的使用者,匿名使用者和公共使用者。
  2. 使用者可以同時擁有匿名和公開個人資料。
  3. 公共和匿名使用者可以關注匿名和公共。
  4. 匿名使用者和公共使用者不得被客戶辨識。這意味著如果我知道公共使用者,我不應該能夠獲取匿名個人資料詳細資訊,反之亦然。

我首先提出了一個想法:

User (id, anon_id,public_id)
AnonymousUser(id(PK,FK),nickname)
PublicUser(id(PK,FK),nickname,fullname,phone,is_phone_registered)
RelationShip(id,follower_id(FK-User),following_id(FK-User))
Tweet(id, author_id(FK-User),text)

在這個設計中,我可以將使用者分成兩部分。但是,如果我們知道推文的作者 ID,我們將無法了解它是通過公共帳戶還是匿名帳戶發送的。關係中也存在同樣的問題,我們無法理解關注者/關注者是匿名的還是公開的。解決方案可能是向關係澄清追隨者/追隨者類型添加另外 2 個欄位,即。follower_type/following_type 和 Tweet author_type 的另外 1 個欄位。

我覺得更正確的另一個解決方案是

User(id(PK),nickname,fullname,phone,is_phone_registered,public)

在這個設計中,我可以在同一個表中同時擁有匿名和公共配置文件。記錄看起來像:

公共領域不應該對客戶可見,所以我在安全方面幾乎實現了我的目標。

對不起我的無知我有 NoSql 背景和在 sql 世界我覺得我需要實現:

  1. 表中的單一職責
  2. 去掉很多多餘的空值
  3. 感覺自引用列是一種反模式,它是公共欄位正在引用其他行 id。

歡迎所有建議。

根據您的要求,使用者可以擁有公共帳戶和匿名帳戶 - 但是,這些帳戶必須分開,這需要一個專有子類型,因此不同的帳戶具有不同的UserIds/ NickNames。但我們還需要維護公共賬戶和匿名賬戶之間的關係。由於公共使用者不能由匿名帳戶擁有,因此該關係保留給匿名使用者子類型。

CREATE TABLE UserType
(
 UserTypeCd  CHAR(1)      NOT NULL  /* P - Public, A - Anonymous, etc */
,Name        VARCHAR(50)  NOT NULL
,CONSTRAINT PK_UserType PRIMARY KEY (UserTypeCd)
,CONSTRAINT AK_UserType UNIQUE (Name)
)
;

CREATE TABLE User
(
 UserId      INT          NOT NULL
,UserTypeCd  CHAR(1)      NOT NULL
,NickName    VARCHAR(20)  NOT NULL
,CONSTRAINT FK_User_One_Of_UserType FOREIGN KEY (UserTypeCd) REFERENCES UserType (UserTypeCd)
,CONSTRAINT PK_User PRIMARY KEY (UserId)
,CONSTRAINT AK_User UNIQUE (NickName)
)
;

CREATE TABLE PublicUser
(
 PublicUserId  INT           NOT NULL
,FullName      VARCHAR(100)  NOT NULL
,PhoneNumber   VARCHAR(15)   NULL
,CONSTRAINT FK_PublicUser_Is_User FOREIGN KEY (PublicUserId) REFERENCES User (UserId)
,CONSTRAINT PK_PublicUser PRIMARY KEY (PublicUserId)
)
;

CREATE TABLE AnonymousUser
(
 AnonymousUserId  INT  NOT NULL
,PublicUserId     INT  NOT NULL
,CONSTRAINT FK_AnonymousUser_Is_User FOREIGN KEY (AnonymousUserId) REFERENCES User (UserId)
,CONSTRAINT FK_AnonymousUser_Owned_By_PublicUser FOREIGN KEY (PublicUserId) REFERENCES PublicUser (PublicUserId)
,CONSTRAINT PK_AnonymousUser PRIMARY KEY (AnonymousUserId)
,CONSTRAINT AK_AnonymousUser UNIQUE (PublicUserId) /* Use if a public user can only have one anonymous account */
)
;

最後一個要求是創建檢查以確保維護PublicUser和之間的排他性AnonymousUser- 這可以通過函式和檢查約束(SQL Server、Sybase)或AFTER INSERT觸發器(其他一切)來完成。基本上,在將行插入其中一個子類型表後,觸發器將查詢User以獲取UserTypeCd. 如果程式碼匹配,則允許送出事務。如果不是,則回滾事務。

我假設匿名使用者必須與公共使用者相關聯。如果不是這種情況,我們將其實現PublicUserId為可選列,如下所示:

CREATE TABLE AnonymousUser
(
 AnonymousUserId  INT  NOT NULL
,CONSTRAINT FK_AnonymousUser_Is_User FOREIGN KEY (AnonymousUserId) REFERENCES User (UserId)
,CONSTRAINT PK_AnonymousUser PRIMARY KEY (AnonymousUserId)
)
;

CREATE TABLE AnonymousUserOwner
(
 AnonymousUserId  INT  NOT NULL
,PublicUserId     INT  NOT NULL
,CONSTRAINT FK_AnonymousUserOwner_For_AnonymousUser FOREIGN KEY (AnonymousUserId) REFERENCES AnonymousUser (AnonymousUserId)
,CONSTRAINT FK_AnonymousUserOwner_Is_PublicUser FOREIGN KEY (PublicUserId) REFERENCES PublicUser (PublicUserId)
,CONSTRAINT PK_AnonymousUserOwner PRIMARY KEY (AnonymousUserId)
,CONSTRAINT AK_AnonymousUserOwner UNIQUE (PublicUserId) /* Use if a public user can only have one anonymous account */


)
;

其他注意事項:

  1. 它看起來Is_Phone_Registered只是一個指標 if PhoneNumberis NULL。如果是這種情況,則無需儲存此值,即可導出。
  2. 如果您使用Id列,則需要在每個實體的上下文中為它們命名UserIdTweetId例如 、 等。
  3. 對於Relationship,不需要該Id列,您的主鍵是(FollowingId, FollowerId)(兩個 FK 引用回User)。不需要額外的列。

引用自:https://dba.stackexchange.com/questions/283860