如何在 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
那么,我的问题是:
我应该使用什么模型来表示 Postgres 中的消息?
如何在数据库中搜索邮件,以便用户在收件箱中立即收到邮件通知并回复?
使用套接字(Phoenix 中的通道)是否会像使用聊天类型的功能那样使工作变得更容易?
首先,抱歉,我对phoenix
不是很熟悉,所以我尽量回答您的问题。
- 您可以在 postgresql 中使用 ARRAY 类型:
这样:
CREATE TABLE message (
from_user text,
to_users text[],
cc_users text[],
body text
...
);
你可以运行这样的查询:
SELECT * FROM message WHERE '$uid' = ANY (to);
设计
消息处理架构可能涉及 app_users
和 messages
之间的 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
我正在使用 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
那么,我的问题是:
我应该使用什么模型来表示 Postgres 中的消息?
如何在数据库中搜索邮件,以便用户在收件箱中立即收到邮件通知并回复?
使用套接字(Phoenix 中的通道)是否会像使用聊天类型的功能那样使工作变得更容易?
首先,抱歉,我对phoenix
不是很熟悉,所以我尽量回答您的问题。
- 您可以在 postgresql 中使用 ARRAY 类型:
这样:
CREATE TABLE message (
from_user text,
to_users text[],
cc_users text[],
body text
...
);
你可以运行这样的查询:
SELECT * FROM message WHERE '$uid' = ANY (to);
设计
消息处理架构可能涉及 app_users
和 messages
之间的 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