如何在没有物化视图的情况下在PostgreSQL中基于postgis操作维护两个表的多对一关系

问题描述 投票:0回答:1

我在 PostgreSQL 中有两个表,

device
block
,具有基于地理空间位置的多对一关系。考虑到地理空间操作的昂贵性质和查询的频率,我希望维护表中的地理空间关系,以避免在每个查询运行时进行 ST 操作。当块或设备的几何形状发生变化时,我需要有效地更新受影响设备的 block_id。

我考虑过使用物化视图,但我了解到许多下游 PostgreSQL 数据复制系统(例如 AWS 中的 DynamoDB)无法同步物化视图。在不使用物化视图的情况下实现这一目标的最佳方法是什么?

postgresql postgis
1个回答
0
投票

您可以将 PostgreSQL 触发器与 PostGIS 函数结合使用。这种方法可以在发生变化时维护关系,并避免在常规查询期间进行昂贵的地理空间操作。

1.将 block_id 添加到设备表中:

首先,将 block_id 列添加到您的设备表中(如果尚未添加):

ALTER TABLE device ADD COLUMN block_id INTEGER;
2.根据地理空间交叉点更新 block_id:

创建触发器函数,根据地理空间交集更新设备表中的 block_id 列

CREATE OR REPLACE FUNCTION update_block_id()
RETURNS TRIGGER AS $$
BEGIN
    NEW.block_id := (
        SELECT id FROM block 
        WHERE ST_Intersects(block.geom, NEW.geom)
        LIMIT 1
    );
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

将触发器附加到设备表:

CREATE OR REPLACE TRIGGER tr_update_device_block_id
BEFORE INSERT OR UPDATE OF geom ON device
FOR EACH ROW
EXECUTE FUNCTION update_block_id();
3.处理块几何形状的变化:

在块表上设置 AFTER UPDATE 触发器,以根据块表几何形状的更改处理设备表中的更新:

触发功能:

CREATE OR REPLACE FUNCTION update_all_devices_for_block()
RETURNS TRIGGER AS $$
BEGIN
    -- Update the block_id for all device records where their geom intersects with the updated block
    UPDATE device SET block_id = NEW.id
    WHERE ST_Intersects(NEW.geom, device.geom);

    -- Set block_id to NULL for device records that no longer intersect with the updated block
    -- assumption: the block.id is the primary key and never changes after a record is created.
    UPDATE device SET block_id = NULL
    WHERE NOT ST_Intersects(NEW.geom, device.geom) AND block_id = NEW.id;

    RETURN NULL;
END;
$$ LANGUAGE plpgsql;

将触发器附加到块表:

CREATE OR REPLACE TRIGGER tr_update_blocks_for_device
AFTER UPDATE OF geom ON block
FOR EACH ROW
EXECUTE FUNCTION update_all_devices_for_block();
4.处理块记录的删除:

您还需要确保如果删除块记录,则相应的设备记录的 block_id 设置为 NULL。为此,您可以创建一个触发器函数并将其附加到块表:

触发功能:

CREATE OR REPLACE FUNCTION update_devices_for_deleted_block()
RETURNS TRIGGER AS $$
BEGIN
    -- Set block_id to NULL for device records that were associated with the deleted block
    UPDATE device SET block_id = NULL
    WHERE block_id = OLD.id;

    RETURN NULL;
END;
$$ LANGUAGE plpgsql;

将触发器附加到块表:

CREATE OR REPLACE TRIGGER tr_update_devices_for_deleted_block
AFTER DELETE ON block
FOR EACH ROW
EXECUTE FUNCTION update_devices_for_deleted_block();

通过此设置,您可以高效地维护和更新地理空间关系,而无需依赖物化视图,从而确保与 DynamoDB 等下游复制系统的兼容性。

© www.soinside.com 2019 - 2024. All rights reserved.