如何在 Postgres 数据库中建模消息

How to model messages in Postgres Database

我正在使用 Phoenix Framework v1.1.0 和 Postgres v9.4 构建一个包含消息传递功能的应用程序。我指的不是即时消息,而是邮件类型的消息,用户可以在其中创建消息并将其发送给 1 个或多个其他用户,而这些用户又可以回复。我不太擅长 SQL 数据库,更习惯 MongoDB 使用 Meteor。在 Postgres 中对这种类型的 table 进行建模以便将消息传递给 1 个或多个用户并进行响应的最有效方法是什么?我最初想创建一个收件人数组,但我被困在那里,我确信有更好的方法。我的架构如下所示:

create table(:messages) do
  add :from, :string
  add :subject, :string
  add :body, :text
  add :to, :array, :string
  timestamps

那么,我的问题是:

  1. 我应该使用什么模型来表示 Postgres 中的消息?

  2. 如何在数据库中搜索邮件,以便用户在收件箱中立即收到邮件通知并回复?

  3. 使用套接字(Phoenix 中的通道)是否会像使用聊天类型的功能那样使工作变得更容易?

首先,抱歉,我对phoenix不是很熟悉,所以我尽量回答您的问题。

  1. 您可以在 postgresql 中使用 ARRAY 类型:

这样:

CREATE TABLE message (
    from_user            text,
    to_users             text[],
    cc_users             text[],
    body                 text
    ...
);
  1. 你可以运行这样的查询:

    SELECT * FROM message WHERE '$uid' = ANY (to);

设计

消息处理架构可能涉及 app_usersmessages 之间的 many-to-many 关系。这将利用Postgres数据库的关系特性。

在table users_messages 中至少有一行是邮件收件人。您可以在另一个词典 table 中添加诸如 DW、UDW 等角色,并将有关收件人类型的信息放入此 table.

CREATE TABLE app_users ( -- one user is represented as one row here
 id serial primary key,
 ...
);

CREATE TABLE messages ( -- one message is represented as one row here
 id bigserial primary key,
 id_sender int references app_users(id),
 send_date timestamp default clock_timestamp(),
 notify_date timestamp default null,
 ...
);

CREATE TABLE users_messages ( -- one message is represented as 1..* rows here
 id bigserial primary key, -- I prefer to use sequences in every table, that's up to you
 id_recipient int references app_users(id),
 id_message bigint references messages(id),
 is_read boolean,
 ...
);

新/未读消息查询

我选择了 DISTINCT,因为您只想通知特定用户收件箱中有新邮件,而不是它们是什么邮件。

获取收件人收件箱中未读邮件通知的查询非常简单:

SELECT DISTINCT id_recipient
FROM users_messages
WHERE is_read is FALSE

如果您需要通知用户关于上次获取的更改状态,例如您可以从 messages table 中获取此信息,如下所示:

SELECT DISTINCT um.id_recipient
FROM messages m
LEFT JOIN users_messages um
WHERE m.notify_date is NULL
      AND um.is_read is FALSE

并为所有获取的 messages.id 更新列 messages.notify_date,这可以在 SQL 或您的框架中完成。这将需要另一个查询,留作 reader.

的练习。

但是,如果您只关心特定用户收到新消息通知,而不提醒他有一些未读消息(这实际上是电子邮件通知的工作方式 ) 那么你可以通过 运行:

SELECT DISTINCT um.id_recipient
FROM messages m
LEFT JOIN users_messages um
WHERE m.notify_date is NULL