Thuộc Thiết Kế CSDL — Nhóm Discovery & Matching
Chi Tiết Entity — Discovery & Matching¶
Bảng:
discovery_session,extracted_field,matching_result
discovery_session¶
CREATE TABLE discovery_session (
id BIGSERIAL PRIMARY KEY,
public_id UUID NOT NULL DEFAULT uuidv7(), -- ID public cho API/external integration
organization_unit_id BIGINT NOT NULL REFERENCES organization_unit(id),
method TEXT NOT NULL
CHECK (method IN ('CSV', 'SQL_DDL', 'MANUAL')),
status TEXT NOT NULL DEFAULT 'PROCESSING'
CHECK (status IN ('PROCESSING', 'COMPLETED', 'FAILED')),
system_name TEXT NOT NULL, -- Tên hệ thống/CSDL nguồn (VD: HIS_BENHVIEN)
file_name TEXT, -- Tên file upload (không lưu nội dung)
file_path TEXT, -- Đường dẫn file trên local filesystem
fields_found INTEGER, -- Số field đã trích xuất
tables_found INTEGER, -- Số bảng (nếu DDL)
error_message TEXT, -- Thông báo lỗi (nếu FAILED)
created_by BIGINT NOT NULL REFERENCES app_user(id),
completed_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
-- KHÔNG lưu: host, port, username, password, connection string (bảo mật)
);
CREATE UNIQUE INDEX idx_ds_public_id ON discovery_session (public_id);
CREATE INDEX idx_ds_org_date ON discovery_session (organization_unit_id, created_at DESC);
CREATE INDEX idx_ds_status ON discovery_session (status);
CREATE INDEX idx_ds_failed ON discovery_session (status) WHERE status = 'FAILED';
Business Rules:
- GĐ1 hỗ trợ 3 method: CSV, SQL_DDL, MANUAL (LDOP, POSTGRES_DIRECT → GĐ2)
- file_path trỏ đến local filesystem (Docker volume /data/uploads/)
- File gốc lưu trữ để truy vết, nhưng metadata đã parse vào extracted_field
- Credentials Discovery (nếu có GĐ2) KHÔNG BAO GIỜ lưu vào DB
extracted_field¶
CREATE TABLE extracted_field (
id BIGSERIAL PRIMARY KEY,
public_id UUID NOT NULL DEFAULT uuidv7(), -- ID public cho API/external integration
discovery_session_id BIGINT NOT NULL REFERENCES discovery_session(id),
table_name TEXT, -- Tên bảng gốc (nullable cho CSV)
schema_name TEXT, -- Tên schema (nullable)
column_name TEXT NOT NULL, -- Tên field gốc
data_type TEXT, -- Kiểu dữ liệu (VD: VARCHAR(12), INTEGER)
max_length INTEGER, -- Độ dài tối đa (nullable)
is_nullable BOOLEAN, -- Nullable flag
description TEXT, -- Mô tả nghiệp vụ (nếu có từ Excel/manual)
matching_status TEXT NOT NULL DEFAULT 'PENDING'
CHECK (matching_status IN ('PENDING', 'MATCHED', 'UNMATCHED', 'REJECTED')),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE UNIQUE INDEX idx_ef_public_id ON extracted_field (public_id);
CREATE INDEX idx_ef_session ON extracted_field (discovery_session_id);
CREATE INDEX idx_ef_matching_status ON extracted_field (matching_status);
CREATE INDEX idx_ef_column_trgm ON extracted_field USING GIN (column_name gin_trgm_ops);
Business Rules:
- Tạo tự động khi parse Discovery session thành công
- matching_status thay đổi sau AI matching hoặc Manager review
- Manager có thể chỉnh sửa field đã parse (VD: sửa tên, kiểu dữ liệu)
matching_result¶
CREATE TABLE matching_result (
id BIGSERIAL PRIMARY KEY,
public_id UUID NOT NULL DEFAULT uuidv7(), -- ID public cho API/external integration
extracted_field_id BIGINT NOT NULL REFERENCES extracted_field(id),
data_element_id BIGINT NOT NULL REFERENCES data_element(id),
confidence_score NUMERIC(4,3) NOT NULL, -- 0.000 – 1.000
match_method TEXT NOT NULL
CHECK (match_method IN ('AUTO_RULE', 'AUTO_AI', 'MANUAL')),
match_status TEXT NOT NULL DEFAULT 'SUGGESTED'
CHECK (match_status IN ('SUGGESTED', 'ACCEPTED', 'REJECTED')),
algo_breakdown JSONB, -- Chi tiết scoring (xem cấu trúc bên dưới)
reviewed_by BIGINT REFERENCES app_user(id),
reviewed_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE UNIQUE INDEX idx_mr_public_id ON matching_result (public_id);
CREATE INDEX idx_mr_field ON matching_result (extracted_field_id);
CREATE INDEX idx_mr_de ON matching_result (data_element_id, match_status);
CREATE INDEX idx_mr_status ON matching_result (match_status);
CREATE INDEX idx_mr_score ON matching_result (confidence_score DESC);
CREATE UNIQUE INDEX idx_mr_one_accepted_per_field
ON matching_result (extracted_field_id)
WHERE match_status = 'ACCEPTED';
Cấu trúc algo_breakdown JSONB:
{
"best_match": {
"de_id": 101,
"confidence": 0.94,
"score_synonym": 1.0,
"score_trigram": 0.87,
"score_levenshtein": 0.80,
"data_type_penalty": false
},
"top5_candidates": [
{ "de_id": 101, "confidence": 0.94, "name": "Số CCCD" },
{ "de_id": 102, "confidence": 0.61, "name": "Họ và tên" }
],
"algo_version": "rule-based-v1.0",
"processed_at": "2026-04-08T14:30:00+07:00"
}
Business Rules:
- GĐ1: Tất cả match_status khởi tạo = SUGGESTED. Manager review 100% (không auto-accept)
- Một extracted_field có thể có nhiều matching_result (top-N candidates), nhưng chỉ 1 ACCEPTED
- algo_breakdown lưu đầy đủ để giải thích + training data cho ML GĐ2
- Score ≥ 0.90 → AI_HIGH_CONFIDENCE (trong source_mapping)
- Score ≥ 0.60 → AI_SUGGESTED (trong source_mapping)
- Score < 0.60 → Không tạo matching_result
Cập nhật lần cuối: 2026-04-08