Mysql
類似 Twitter 的應用程序中的匿名和公共使用者表設計
我有架構設計問題,我不能 100% 確定我的假設是否正確。
所以要求是:
- 我需要有 2 種不同類型的使用者,匿名使用者和公共使用者。
- 使用者可以同時擁有匿名和公開個人資料。
- 公共和匿名使用者可以關注匿名和公共。
- 匿名使用者和公共使用者不得被客戶辨識。這意味著如果我知道公共使用者,我不應該能夠獲取匿名個人資料詳細資訊,反之亦然。
我首先提出了一個想法:
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 世界我覺得我需要實現:
- 表中的單一職責
- 去掉很多多餘的空值
- 感覺自引用列是一種反模式,它是公共欄位正在引用其他行 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 */ ) ;
其他注意事項:
- 它看起來
Is_Phone_Registered
只是一個指標 ifPhoneNumber
isNULL
。如果是這種情況,則無需儲存此值,即可導出。- 如果您使用
Id
列,則需要在每個實體的上下文中為它們命名UserId
,TweetId
例如 、 等。- 對於
Relationship
,不需要該Id
列,您的主鍵是(FollowingId
,FollowerId)
(兩個 FK 引用回User
)。不需要額外的列。