Thiết kế mô hình dữ liệu cho ứng dụng theo dõi liều thuốc GLP-1
Khi xây dựng một ứng dụng theo dõi liều thuốc GLP-1 (semaglutide, tirzepatide, liraglutide), phần khó nhất không phải là giao diện mà là mô hình dữ liệu. Dưới đây là những gì tôi rút ra được sau khi thiết kế schema cho bài toán này.
1. Đừng lưu liều dùng dưới dạng một con số
Liều GLP-1 được kê theo miligam, nhưng bệnh nhân tiêm theo đơn vị trên ống bút hoặc theo mililít khi dùng lọ. Một bút 2.4 mg/3 mL không giống một bút 2.4 mg/0.75 mL. Nếu bạn chỉ lưu dose = 2.4, bạn sẽ mất thông tin để hiển thị lại đúng cho người dùng.
Cách làm an toàn hơn là lưu ba trường tách biệt:
CREATE TABLE dose_event (
id UUID PRIMARY KEY,
user_id UUID NOT NULL,
medication_id UUID NOT NULL,
amount_mcg INTEGER NOT NULL, -- luôn quy về microgam, số nguyên
concentration_mcg_per_ml INTEGER, -- để tính lại thể tích
taken_at TIMESTAMPTZ NOT NULL,
taken_at_tz TEXT NOT NULL, -- IANA tz tại thời điểm tiêm
site TEXT, -- vị trí tiêm luân phiên
note TEXT
);
Dùng số nguyên microgam thay vì FLOAT mg. Liều 0.25 mg biểu diễn bằng float sẽ tích lũy sai số khi bạn cộng dồn theo tuần, và với dữ liệu y tế thì sai số kiểu đó là không chấp nhận được.
2. Múi giờ: lưu cả timestamp lẫn tên múi giờ
Đây là lỗi phổ biến nhất. Người dùng tiêm vào tối thứ Bảy, rồi đi công tác qua múi giờ khác. Nếu bạn chỉ lưu TIMESTAMPTZ, câu hỏi "tuần này tôi đã tiêm chưa" sẽ trả lời sai, vì ranh giới ngày/tuần phụ thuộc vào múi giờ địa phương của người dùng lúc đó, không phải UTC. Lưu thêm taken_at_tz cho phép bạn tái tạo chính xác ngày địa phương về sau.
3. Lịch tăng liều là dữ liệu, không phải mã nguồn
Phác đồ GLP-1 tăng liều theo bậc, thường 4 tuần mỗi bậc. Rất dễ hard-code chuỗi bậc vào một mảng trong code. Đừng làm vậy: bác sĩ thường xuyên giữ bệnh nhân ở một bậc lâu hơn vì tác dụng phụ tiêu hóa, hoặc lùi lại một bậc. Hãy mô hình hóa nó thành bảng titration_step (medication_id, step_index, amount_mcg, min_weeks) và cho phép người dùng ghi đè.
4. Chống ghi trùng bằng idempotency key
Thông báo nhắc nhở + nhiều thiết bị = ghi trùng. Một UNIQUE (user_id, medication_id, date_trunc('day', taken_at AT TIME ZONE taken_at_tz)) là ràng buộc rẻ tiền và chặn được phần lớn trường hợp, vì hầu như không ai tiêm cùng một thuốc hai lần trong một ngày.
5. Xuất dữ liệu là tính năng bắt buộc
Người dùng sẽ mang dữ liệu này đi khám. Một endpoint xuất CSV với cột date, medication, dose_mg, site, note đáng giá hơn mười biểu đồ đẹp. Hãy để cột liều ở đơn vị mg cho bản xuất — đó là đơn vị bác sĩ đọc.
Kết
Tôi đã áp dụng những nguyên tắc trên khi làm glp1.app, một công cụ theo dõi liều GLP-1 chạy trên web. Ba điểm khiến tôi phải viết lại schema nhiều nhất là đơn vị đo, múi giờ và lịch tăng liều — nếu bạn làm ứng dụng sức khỏe tương tự, hãy xử lý ba thứ đó trước khi viết dòng CSS đầu tiên.
All rights reserved