我正在使用SQLAlchemy和PostgreSQL开发应用程序。系统用户修改8个左右表中的数据。考虑这个人为的示例模式:
我想将可见记录添加到系统中以记录已更改的内容,但不一定记录它的更改方式。例如:"用户A修改后的产品Foo","用户A添加了用户B"或"用户C购买了产品Bar"。所以基本上我想存储:
product_id
和customer_id
,以便用户可以点击该实体我想在每个用户登录应用程序时显示最近和相关的更改列表(有点像Facebook等主要时间轴)。我想存储订阅,以便用户可以订阅更改,例如"告诉我产品X何时被修改"或者"告诉我商店S中的任何产品何时被修改"。
我见过audit trigger recipe,但我不确定它是我想要的。该审核触发器可以很好地完成录制更改,但是如何快速过滤它以显示用户最近的相关更改?我考虑的选项:
任何见解都表示赞赏:)
编辑我似乎正在谈论activity stream。 this answer中按时间过滤的建议听起来不错。
答案 0 :(得分:1)
由于对象都使用uuid
enum
字段,我想我会像这样创建活动表:
uuid
列没有外键,text[]
列指定它引用的对象类型。SELECT *
FROM (
SELECT DISTINCT ON (activity.created, activity.id)
*
FROM activity
LEFT OUTER JOIN unnest(activity.object_ref) WITH ORDINALITY AS act_ref
ON true
LEFT OUTER JOIN subscription
ON subscription.object_id = act_ref.act_ref
WHERE activity.created BETWEEN :lower_date AND :upper_date
AND subscription.user_id = :user_id
ORDER BY activity.created DESC,
activity.id,
act_ref.ordinality DESC
) AS sub
WHERE sub.subscribed = true;
(可能为unnest(...) WITH ORDINALITY
)(例如父类别,商店和组织),并搜索数组以进行前进订阅。这样,父类别的订阅可以在一个步骤中匹配子项(非规范化)。我可能会先按时间过滤以减少所需的搜索量。稍后,如果需要,我会看看使用GIN索引数组列(这部分回答了我的问题“是否有以灵活方式索引hstore的技巧?”)
更新这项运作良好。获取时间轴的SQL看起来像这样:
unnest
加入@>
,按惯例排序,并在活动ID上选择不同,过滤掉在更深层次上 un 订阅的活动。如果您不需要这样做,那么您可以避免使用SELECT *
FROM activity
JOIN subscription ON activity.object_ref @> subscription.object_id
WHERE subscription.user_id = :user_id
AND activity.created BETWEEN :lower_date AND :upper_date
ORDER BY activity.created DESC;
并使用数组包含title
运算符,而不使用子查询:
activity
您也可以与其他对象表连接以获取对象标题 - 但我决定在{{1}}表中添加{{1}}列。这是非规范化的,但它不需要与许多表的复杂连接,并且它允许删除对象(可能是触发活动记录的操作)。