構建一個即時訊息應用(一):模式

2019-09-27 21:15:00

這是一系列關於構建“即時訊息”應用的新貼文。你應該對這類應用並不陌生。有了它們的幫助,我們才可以與朋友暢聊無忌。Facebook MessengerWhatsAppSkype 就是其中的幾個例子。正如你所看到的那樣,這些應用允許我們傳送圖片、傳輸視訊、錄製音訊、以及和一大幫子人聊天等等。當然,我們的教學應用將會盡量保持簡單,只在兩個使用者之間傳送文字訊息。

我們將會用 CockroachDB 作為 SQL 資料庫,用 Go 作為後端語言,並且用 JavaScript 來製作 web 應用。

這是第一篇貼文,我們將會講述資料庫的設計。

CREATE TABLE users (    id SERIAL NOT NULL PRIMARY KEY,    username STRING NOT NULL UNIQUE,    avatar_url STRING,    github_id INT NOT NULL UNIQUE);

顯然,這個應用需要一些使用者。我們這裡採用社交登入的形式。由於我選用了 GitHub,所以這裡需要儲存一個對 GitHub 使用者 ID 的參照。

CREATE TABLE conversations (    id SERIAL NOT NULL PRIMARY KEY,    last_message_id INT,    INDEX (last_message_id DESC));

每個對話都會參照最近一條訊息。每當我們輸入一條新訊息時,我們都會更新這個欄位。我會在後面新增外來鍵約束。

… 你可能會想,我們可以先對對話進行分組,然後再通過這樣的方式獲取最近一條訊息。但這樣做會使查詢變得更加複雜。

CREATE TABLE participants (    user_id INT NOT NULL REFERENCES users ON DELETE CASCADE,    conversation_id INT NOT NULL REFERENCES conversations ON DELETE CASCADE,    messages_read_at TIMESTAMPTZ NOT NULL DEFAULT now(),    PRIMARY KEY (user_id, conversation_id));

儘管之前我提到過對話只會在兩個使用者之間進行,但我們還是採用了允許向對話中新增多個參與者的設計。因此,在對話和使用者之間有一個參與者表。

為了知道使用者是否有未讀訊息,我們在訊息表中新增了“讀取時間”(messages_read_at)欄位。每當使用者在對話中讀取訊息時,我們都會更新它的值,這樣一來,我們就可以將它與對話中最後一條訊息的“建立時間”(created_at)欄位進行比較。

CREATE TABLE messages (    id SERIAL NOT NULL PRIMARY KEY,    content STRING NOT NULL,    user_id INT NOT NULL REFERENCES users ON DELETE CASCADE,    conversation_id INT NOT NULL REFERENCES conversations ON DELETE CASCADE,    created_at TIMESTAMPTZ NOT NULL DEFAULT now(),    INDEX(created_at DESC));

儘管我們將訊息表放在最後,但它在應用中相當重要。我們用它來儲存對建立它的使用者以及它所出現的對話的參照。而且還可以根據“建立時間”(created_at)來建立索引以完成對訊息的排序。

ALTER TABLE conversationsADD CONSTRAINT fk_last_message_id_ref_messagesFOREIGN KEY (last_message_id) REFERENCES messages ON DELETE SET NULL;

我在前面已經提到過這個外來鍵約束了,不是嗎:D

有這四張表就足夠了。你也可以將這些查詢儲存到一個檔案中,並將其通過管道傳送到 Cockroach CLI。

首先,我們需要啟動一個新節點:

cockroach start --insecure --host 127.0.0.1

然後建立資料庫和這些表:

cockroach sql --insecure -e "CREATE DATABASE messenger"cat schema.sql | cockroach sql --insecure -d messenger

這篇貼文就到這裡。在接下來的部分中,我們將會介紹「登入」,敬請期待。