Thuộc Thiết Kế CSDL — Nhóm Anchored Data
Chi Tiết Entity — Anchored Data¶
Bảng:
domain,sub_domain,data_element,extension_proposal,data_lineage
domain¶
CREATE TABLE domain (
id BIGSERIAL PRIMARY KEY,
public_id UUID NOT NULL DEFAULT uuidv7(), -- ID public cho API/external integration
code TEXT UNIQUE NOT NULL, -- DM{N} (VD: DM1, DM2). Bất biến sau khi tạo
name TEXT NOT NULL, -- Tên lĩnh vực (VD: Con người, Tổ chức)
description TEXT, -- Mô tả chi tiết
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE UNIQUE INDEX idx_dm_public_id ON domain (public_id);
Business Rules:
- code tự sinh theo format DM{N} — không cho sửa sau khi tạo
- Không xóa Domain nếu còn Sub Domain con
- Chỉ Manager được tạo Domain
sub_domain¶
CREATE TABLE sub_domain (
id BIGSERIAL PRIMARY KEY,
public_id UUID NOT NULL DEFAULT uuidv7(), -- ID public cho API/external integration
code TEXT UNIQUE NOT NULL, -- DM{N}.{M} (VD: DM1.1). Bất biến
domain_id BIGINT NOT NULL REFERENCES domain(id),
name TEXT NOT NULL, -- Tên phân nhóm
description TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE UNIQUE INDEX idx_sd_public_id ON sub_domain (public_id);
CREATE INDEX idx_sd_domain ON sub_domain (domain_id);
Business Rules:
- code tự sinh format DM{N}.{M} — prefix phải khớp Domain cha
- Không xóa Sub Domain nếu còn Data Element con
- Data Owner đề xuất qua extension_proposal
data_element¶
Lưu trữ các từ ngữ chuyên ngành và dữ liệu cốt lõi đã được chuẩn hóa. Bảng này đã được thiết kế gộp với khái niệm Dictonary Term (Từ điển) phục vụ AI Suggestion Worker, và sử dụng cơ chế SCD Type 2 để lưu vết version.
CREATE TABLE data_element (
id BIGSERIAL PRIMARY KEY,
public_id UUID NOT NULL DEFAULT uuidv7(), -- ID public cho API/external integration
code TEXT NOT NULL, -- Mã định danh tự sinh (DE{NNN}-DM{N}.{M})
name TEXT NOT NULL, -- Tên nghiệp vụ chuẩn (Term)
sub_domain_id BIGINT NOT NULL REFERENCES sub_domain(id),
status TEXT NOT NULL DEFAULT 'DRAFT'
CHECK (status IN ('DRAFT', 'IN_REVIEW', 'APPROVED', 'PUBLISHED', 'ARCHIVED')),
data_type TEXT NOT NULL, -- Kiểu dữ liệu gốc (VARCHAR, DATE...)
-- Danh mục & Pháp lý
reference_catalog_id BIGINT REFERENCES reference_catalog(id), -- Tham chiếu nếu field là danh mục định sẵn
legal_document_id BIGINT REFERENCES legal_document(id), -- Cơ sở pháp lý chuẩn hóa (ưu tiên dùng nếu có trong catalog)
national_mapped_id TEXT, -- ID trên Nền tảng chia sẻ dữ liệu quốc gia NDXP
is_personal_data BOOLEAN DEFAULT FALSE, -- Đánh dấu Dữ liệu cá nhân (theo NĐ13/2023)
-- SCD Type 2
version_number INTEGER DEFAULT 1,
effective_from TIMESTAMPTZ NOT NULL DEFAULT NOW(),
effective_to TIMESTAMPTZ, -- NULL = Phiên bản đang active
is_current BOOLEAN DEFAULT TRUE, -- Cờ tối ưu query lấy phiên bản hiện hành
-- Quản trị dữ liệu (Bảng D & Metadata)
sensitivity_level TEXT NOT NULL DEFAULT 'INTERNAL'
CHECK (sensitivity_level IN ('PUBLIC', 'INTERNAL', 'CONFIDENTIAL', 'SECRET')),
owner_unit_id BIGINT REFERENCES organization_unit(id), -- Chủ quản cấp Phòng/Ban (1:1)
is_future BOOLEAN NOT NULL DEFAULT FALSE, -- Dữ liệu tương lai
future_objective TEXT, -- Mục tiêu phát triển (bắt buộc khi is_future=true)
legal_basis TEXT, -- Cơ sở pháp lý dạng tự do (fallback khi chưa có trong catalog)
attributes JSONB DEFAULT '{}', -- 14 thuộc tính nghiệp vụ mở rộng
tech_attributes JSONB DEFAULT '{}', -- 11 thuộc tính kỹ thuật mở rộng
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT chk_de_tu_dong_nghia_size CHECK (
jsonb_array_length(attributes->'tu_dong_nghia') <= 10
AND length(attributes->>'tu_dong_nghia') < 1000
),
CONSTRAINT chk_de_legal_reference_rule CHECK (
status != 'APPROVED'
OR (
(legal_document_id IS NOT NULL AND legal_basis IS NULL)
OR (legal_document_id IS NULL AND legal_basis IS NOT NULL)
)
),
CONSTRAINT chk_de_owner_required_by_status CHECK (
status NOT IN ('APPROVED', 'PUBLISHED')
OR owner_unit_id IS NOT NULL
),
CONSTRAINT chk_de_future_objective_required CHECK (
is_future = FALSE
OR (future_objective IS NOT NULL AND length(btrim(future_objective)) > 0)
)
);
-- Core Index
CREATE UNIQUE INDEX idx_de_public_id ON data_element (public_id);
CREATE INDEX idx_de_subdomain ON data_element (sub_domain_id);
CREATE INDEX idx_de_status ON data_element (status);
CREATE INDEX idx_de_owner ON data_element (owner_unit_id);
-- SCD Type 2 Indexes
CREATE UNIQUE INDEX idx_de_current ON data_element (code) WHERE is_current = TRUE;
CREATE INDEX idx_de_effective ON data_element (effective_from, effective_to);
-- =========================================================================
-- AI Worker Support Indexes (PG_TRGM & GIN)
-- Bắt buộc tạo bằng migration scripts của module AI: 02_Init_AI_Matching_Engine.sql
-- =========================================================================
-- Text fuzzy search (Trigram) cho Tên nghiệp vụ
CREATE INDEX idx_de_name_trgm ON data_element USING GIN (name gin_trgm_ops);
-- Trigram Index cho Tên trường kỹ thuật phục vụ hàm levenshtein() & word_similarity()
CREATE INDEX idx_de_tech_ten_truong_trgm ON data_element USING GIN ((tech_attributes->>'ten_truong_ky_thuat') gin_trgm_ops);
-- GIN B-Tree/Jsonb Index cho `tu_dong_nghia` để Operator @> (Exact match) đạt O(log N)
CREATE INDEX idx_de_tu_dong_nghia_path ON data_element USING GIN ((attributes->'tu_dong_nghia') jsonb_path_ops);
Cấu trúc attributes JSONB (14 thuộc tính nghiệp vụ):
{
"ten_nghiep_vu": "Số CCCD",
"dinh_nghia": "Số căn cước công dân 12 số do Bộ Công an cấp",
"don_vi_tao_lap": "Bộ Công an",
"can_cu_phap_ly": "Luật Căn cước công dân 2014 (giá trị hiển thị, đồng bộ từ legal_document_id hoặc legal_basis)",
"nhom_du_lieu": "Định danh cá nhân",
"tu_dong_nghia": ["so_cccd", "cccd_number", "citizen_id", "cmnd"],
"vi_du": "001234567890",
"ghi_chu": "",
"pham_vi_ap_dung": "Toàn TP",
"tan_suat_cap_nhat": "Khi có thay đổi",
"nguon_du_lieu": "CSDL Quốc gia về dân cư",
"lien_ket_tham_chieu": ""
}
Cấu trúc tech_attributes JSONB (11 thuộc tính kỹ thuật):
{
"ten_truong_ky_thuat": "cccd_so",
"kieu_du_lieu_ky_thuat": "VARCHAR(12)",
"do_dai_toi_da": 12,
"bat_buoc": true,
"gia_tri_mac_dinh": null,
"validation_rules": { "regex": "^[0-9]{12}$" },
"dinh_dang": "############",
"don_vi_do": null,
"he_thong_nguon": "CSDL Công an",
"bang_nguon": "cong_dan",
"lineage_info": {}
}
Business Rules:
- code tự sinh, bất biến
- Mỗi code có thể có nhiều bản ghi lịch sử, nhưng chỉ 1 bản ghi is_current = true
- Cơ sở pháp lý khi status = APPROVED: dùng legal_document_id nếu có trong catalog; nếu chưa có thì dùng legal_basis; không điền đồng thời cả hai
- attributes.can_cu_phap_ly chỉ phục vụ hiển thị/export, không phải source-of-truth pháp lý
- Quy tắc 1:1: mỗi DE chỉ có tối đa 1 owner_unit_id
- owner_unit_id phải tham chiếu đơn vị cấp PHONG trở xuống
- owner_unit_id bắt buộc khi status = APPROVED hoặc PUBLISHED
- is_future = true → future_objective bắt buộc, owner_unit_id có thể NULL
- Không xóa DE khi status = PUBLISHED
extension_proposal¶
CREATE TABLE extension_proposal (
id BIGSERIAL PRIMARY KEY,
public_id UUID NOT NULL DEFAULT uuidv7(), -- ID public cho API/external integration
proposal_type TEXT NOT NULL
CHECK (proposal_type IN ('SUB_DOMAIN', 'DATA_ELEMENT')),
domain_id BIGINT NOT NULL REFERENCES domain(id),
sub_domain_id BIGINT REFERENCES sub_domain(id), -- Chỉ khi type = DATA_ELEMENT
proposed_name TEXT NOT NULL,
proposed_description TEXT,
proposed_data_type TEXT, -- Chỉ khi type = DATA_ELEMENT
justification TEXT NOT NULL, -- Lý do đề xuất
status TEXT NOT NULL DEFAULT 'PENDING'
CHECK (status IN ('PENDING', 'APPROVED', 'REJECTED')),
proposed_by BIGINT NOT NULL REFERENCES app_user(id),
reviewed_by BIGINT REFERENCES app_user(id),
review_note TEXT, -- Lý do chấp nhận/từ chối
created_entity_id BIGINT, -- ID entity đã tạo (nếu APPROVED)
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE UNIQUE INDEX idx_ep_public_id ON extension_proposal (public_id);
CREATE INDEX idx_ep_status ON extension_proposal (status);
CREATE INDEX idx_ep_proposed_by ON extension_proposal (proposed_by);
CREATE INDEX idx_ep_domain ON extension_proposal (domain_id);
Business Rules:
- Data Owner chỉ đề xuất trong Domain đã tồn tại — không tạo Domain mới
- Khi APPROVED → hệ thống tự sinh mã và tạo Sub Domain/DE mới → lưu created_entity_id
- review_note bắt buộc khi REJECTED
data_lineage¶
Bảng mô tả tác động dây chuyền khi một Data Element thay đổi phiên bản hoặc bị thay thế. Hỗ trợ đồ thị Impact Analysis.
CREATE TABLE data_lineage (
id BIGSERIAL PRIMARY KEY,
public_id UUID NOT NULL DEFAULT uuidv7(), -- ID public cho API/external integration
source_element_id BIGINT NOT NULL REFERENCES data_element(id), -- DE bị tác động / phiên bản cũ
target_element_id BIGINT NOT NULL REFERENCES data_element(id), -- DE thay thế / phiên bản mới
transformation_rule TEXT, -- Quy tắc chuyển đổi (VD: Cắt 9 số thành 12 số)
created_by BIGINT NOT NULL REFERENCES app_user(id),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE UNIQUE INDEX idx_dl_public_id ON data_lineage (public_id);
-- Index phục vụ Graph Query hai chiều
CREATE INDEX idx_dl_source ON data_lineage (source_element_id);
CREATE INDEX idx_dl_target ON data_lineage (target_element_id);
Business Rules:
- Khi Data Element nâng phiên bản (SCD Type 2), hệ thống GHI NHẬN 1 bản ghi Lineage từ old_version_id sang new_version_id.
- Tách biệt với SCD Type 2 để hệ thống bên ngoài / API không bị phá vỡ contract gốc, giúp việc phân tích Impact linh hoạt.
Cập nhật lần cuối: 2026-04-11