我们正在实施一个电子商务数据模型,但在Postgres生成的列、Hasura计算字段和Postgres视图之间犹豫不决。
简化而言,我们有两张表:
items
------------
id
order_id
unit_price
quantity
orders
------------
id
我们现在希望在
items
表中添加total_price
(即unit_price * quantity
),并且在订单中添加total_price
(即该订单中所有items
的total_price
之和)。在第一个情况下,我们使用了Postgres生成的列。这里的好处似乎是它只需要生成一次并存储起来,而不像Hasura计算字段那样在每次查询时都要重新运行。
这是正确的选择吗?
items
------------
id
order_id
unit_price
quantity
total_price : Postgres generated column : (unit_price * quantity)
CREATE TABLE orders (
...,
total_price integer GENERATED ALWAYS AS (unit_price * quantity) STORED
);
在第二种情况下,我们无法使用生成的列,因为它不能引用不同表中的字段。相反,我们可以使用Hasura计算字段来解决这个问题。
orders
------------
id
total_price : Hasura computed field : SUM(items.total_price)
CREATE FUNCTION calculate_order_total_price(orders_row orders)
RETURNS INTEGER AS $$
SELECT CAST(SUM(total_price) AS INTEGER)
FROM items
WHERE order_id = orders_row.id
$$ LANGUAGE sql STABLE;
或者,我们可以创建一个Postgres视图:
vw_orders
------------
orders.id
total_price : SELECT SUM(items.total_price)
CREATE VIEW vw_orders AS
SELECT orders.id,
(SELECT sum(items.total_price) AS sum
FROM items
WHERE (items.order_id = orders.id)) AS total_price
FROM orders;
Hasura计算字段的解决方案的缺点是只在GraphQL查询中公开了total_price
,因此我们无法在SQL中使用它。
Postgres视图解决方案乍一看似乎没有任何问题。
我们有什么遗漏吗?
为什么会有人使用Hasura计算字段而不是Postgres生成的字段或视图呢?
是否有比较表或流程图可以帮助我们决定在每种特定情况下哪种方法最好?
最后,对于所有这些,我们当然也可以使用Postgres触发器、Hasura事件触发器和Hasura操作……那么什么时候使用这些才是适当的解决方案?
干杯!