Menu
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Đang tải...

MongoDB và Document DBs: BA cần biết khái niệm

API and Technical Fundamentals cho BA Bài 33/60

Mở đầu — vì sao bài này quan trọng

Khi bạn làm BA cho một dự án phần mềm, có một câu hỏi rất hay xuất hiện ngay từ những buổi họp đầu tiên: "Hệ thống này sẽ lưu dữ liệu vào đâu, và lưu theo kiểu gì?". Trong nhiều năm, câu trả lời mặc định gần như luôn là một database quan hệ (relational database) với các bảng, hàng và cột — kiểu như MySQL hay SQL Server. Nhưng càng ngày bạn càng nghe đội kỹ thuật nhắc tới một cái tên khác: MongoDB. Và họ nói về "document", về "collection", về việc "không cần schema cứng".

Nếu bạn không nắm khái niệm này, sẽ có hai rủi ro rất thực tế. Thứ nhất, bạn viết tài liệu nghiệp vụ (BRD, user story, data dictionary) theo tư duy bảng quan hệ trong khi hệ thống thực tế lưu dữ liệu dạng document — dẫn tới mô tả sai cấu trúc, dev phải làm lại. Thứ hai, khi product owner hỏi "tại sao tính năng tìm kiếm theo nhiều điều kiện lại chậm?" hoặc "tại sao báo cáo tổng hợp khó làm?", bạn không hiểu gốc rễ vấn đề nằm ở lựa chọn loại database, nên không thể tham gia vào quyết định.

Lưu ý quan trọng: bài này KHÔNG đi sâu so sánh tổng quát SQL với NoSQL ở mức chiến lược (việc đó thuộc bài "SQL vs NoSQL"), cũng không nói về Redis hay key-value (bài riêng). Ở đây ta tập trung đúng một thứ: document database, mà MongoDB là đại diện phổ biến nhất. Bạn sẽ hiểu document là gì, collection là gì, dữ liệu trông như thế nào, và quan trọng nhất — với vai trò BA, bạn cần đặt câu hỏi gì khi hệ thống dùng kiểu database này.

Khái niệm cốt lõi

Document là gì?

Hãy bắt đầu từ hình ảnh quen thuộc. Trong database quan hệ, một khách hàng được lưu thành một hàng (row) trong bảng customers, với các cột cố định như id, name, phone, email. Nếu khách hàng có nhiều địa chỉ giao hàng, bạn phải tạo thêm một bảng addresses riêng và nối hai bảng bằng khóa.

Trong document database, mọi thứ làm khác hẳn. Một khách hàng được lưu thành một document — về bản chất là một khối dữ liệu trông giống hệt JSON mà bạn đã học ở các bài trước. Ví dụ:

{
  "_id": "KH00123",
  "ho_ten": "Nguyễn Thị Lan",
  "sdt": "0905123456",
  "email": "lan.nguyen@email.com",
  "dia_chi_giao_hang": [
    { "loai": "nha", "duong": "12 Lê Lợi", "quan": "Hải Châu", "tp": "Đà Nẵng" },
    { "loai": "cong_ty", "duong": "88 Nguyễn Văn Linh", "quan": "Thanh Khê", "tp": "Đà Nẵng" }
  ],
  "diem_tich_luy": 2400
}

Điều đáng chú ý ở đây: toàn bộ thông tin của một khách hàng — kể cả danh sách nhiều địa chỉ — nằm gọn trong một document duy nhất. Bạn không cần "nối bảng" để lấy địa chỉ. Mỗi document tương đương một "record" — một bản ghi trọn vẹn về một thực thể nghiệp vụ.

Collection là gì?

Nếu document giống như một hàng, thì collection giống như một bảng — nó là nhóm các document cùng loại. Bạn sẽ có collection customers chứa tất cả document khách hàng, collection orders chứa tất cả document đơn hàng, v.v.

Tóm tắt nhanh để bạn dịch giữa hai thế giới:

Thế giới quan hệ (SQL)Thế giới document (MongoDB)
DatabaseDatabase
Table (bảng)Collection
Row (hàng)Document
Column (cột)Field (trường)
Khóa chính (primary key)_id (mỗi document tự có)

BSON — anh em ruột của JSON

Bạn sẽ nghe dev nhắc tới BSON (Binary JSON). Đừng hoảng. BSON đơn giản là cách MongoDB lưu document ở dạng nhị phân để máy đọc/ghi nhanh hơn, đồng thời hỗ trợ thêm vài kiểu dữ liệu mà JSON thuần không có (như kiểu ngày tháng Date, kiểu số nguyên 64-bit, kiểu ObjectId). Khi bạn nhìn dữ liệu trên màn hình, nó vẫn hiện ra như JSON quen thuộc. Với vai trò BA, bạn chỉ cần biết: "Dữ liệu bản chất là JSON, lưu dưới dạng nhị phân BSON để tối ưu hiệu năng".

Khái niệm quan trọng nhất với BA: "Schema linh hoạt"

Đây là điểm khiến document database khác biệt nhất, và cũng dễ gây hiểu lầm nhất.

Trong database quan hệ, schema (cấu trúc) là cứng: bảng customers có đúng các cột đã định nghĩa, mọi hàng đều phải tuân theo. Muốn thêm cột mới phải chạy lệnh thay đổi cấu trúc bảng.

Trong MongoDB, các document trong cùng một collection không bắt buộc giống hệt nhau về cấu trúc. Document khách hàng A có thể có trường ngay_sinh, trong khi document khách hàng B không có. Đây gọi là "schema linh hoạt" (flexible schema) hay đôi khi gọi nhầm là "schema-less".

Là BA, bạn cần khắc cốt ghi tâm điều này: "linh hoạt" KHÔNG có nghĩa là "không cần thiết kế". Nó chỉ có nghĩa là việc thiết kế chuyển từ database sang ứng dụng và sang chính bạn. Nếu không ai định nghĩa rõ document nên trông như thế nào, mỗi dev sẽ tự lưu một kiểu, và sáu tháng sau bạn có một collection hỗn loạn với mười biến thể cấu trúc khác nhau. Đây là lý do tài liệu data dictionary của BA càng trở nên quan trọng, chứ không phải bớt quan trọng.

Embedding vs Referencing — quyết định mô hình hóa cốt lõi

Có một quyết định thiết kế mà BA chắc chắn sẽ ngồi cùng dev để bàn: với dữ liệu liên quan, ta nhúng (embed) hay tham chiếu (reference)?

  • Nhúng (embedding): đặt dữ liệu con ngay bên trong document cha — như ví dụ địa chỉ giao hàng nằm trong document khách hàng ở trên. Ưu điểm: đọc một phát ra hết, rất nhanh. Nhược điểm: nếu dữ liệu con quá lớn hoặc thay đổi liên tục độc lập, document phình to và khó quản lý.
  • Tham chiếu (referencing): document chỉ lưu một "con trỏ" (thường là _id) tới document khác trong collection khác — gần giống cách nối bảng của SQL. Ưu điểm: tránh trùng lặp, dữ liệu con sống độc lập. Nhược điểm: phải đọc nhiều lần để ghép dữ liệu lại.
Nguyên tắc thực dụng để bạn nhớ: "dữ liệu nào hay được đọc cùng nhau và thuộc về nhau thì nhúng; dữ liệu nào lớn, dùng chung nhiều nơi, hoặc thay đổi độc lập thì tham chiếu". Quyết định này ảnh hưởng trực tiếp tới hiệu năng và độ phức tạp của API mà bạn đang đặc tả.

Tình huống thực tế

Tình huống 1 — Sàn TMĐT nội địa và bài toán catalog sản phẩm

Một startup thương mại điện tử ở TP.HCM (tạm gọi ChợSố) bán đủ thứ: điện thoại, mỹ phẩm, thời trang, thực phẩm. Nhóm kỹ thuật chọn MongoDB cho catalog sản phẩm, và khi tham gia dự án, BA hơi bối rối vì trước đó quen với mô hình bảng quan hệ.

Vấn đề nghiệp vụ rất rõ: mỗi loại sản phẩm có thuộc tính hoàn toàn khác nhau. Điện thoại cần dung_luong_pin, ram, bo_nho. Mỹ phẩm cần dung_tich, han_su_dung, thanh_phan. Áo cần size, mau_sac, chat_lieu. Nếu dùng một bảng quan hệ duy nhất, bạn sẽ có hàng trăm cột mà 90% là rỗng với mỗi sản phẩm — rất xấu và khó quản.

Với document database, mỗi sản phẩm là một document và chỉ chứa đúng những trường nó cần:

{ "_id": "SP01", "ten": "iPhone 15", "loai": "dien_thoai", "thuoc_tinh": { "ram": "6GB", "bo_nho": "128GB", "pin": "3349mAh" } }
{ "_id": "SP02", "ten": "Son MAC Ruby Woo", "loai": "my_pham", "thuoc_tinh": { "dung_tich": "3g", "han_su_dung": "2027-08" } }

Diễn giải: đây chính là điểm mạnh tự nhiên của document DB — dữ liệu không đồng nhất (heterogeneous). Mỗi document tự do mang cấu trúc thuộc tính riêng. BA viết tài liệu bằng cách mô tả "khung chung" (_id, ten, loai) cộng với "phần thuộc tính động" theo từng loai.

Bài học rút ra: Khi nghiệp vụ có nhiều biến thể thực thể cùng họ nhưng khác thuộc tính, document database thường phù hợp hơn. Vai trò BA là định nghĩa rõ danh sách loai hợp lệ và bộ thuộc tính bắt buộc cho từng loai, nếu không catalog sẽ loạn.

Tình huống 2 — Ngân hàng số và cái bẫy "không cần schema"

Một fintech ở Singapore phát triển ứng dụng ví điện tử. Đội backend mới, hào hứng với MongoDB, lưu giao dịch mà không thống nhất tên trường. Có dev lưu số tiền là amount, người khác lưu so_tien, người thứ ba lưu value; có document để đơn vị là "VND", có document lưu số nguyên đồng, có document lưu số thực.

Sáu tháng sau, khi BA cần làm báo cáo tổng giao dịch theo tháng, mọi thứ vỡ trận. Câu truy vấn "tổng số tiền giao dịch" không thể chạy ngon vì cùng một khái niệm nằm ở ba tên trường khác nhau với ba định dạng khác nhau. Đội phải bỏ ra gần ba tuần chỉ để "dọn dẹp dữ liệu" (data cleansing) và viết script chuẩn hóa.

Diễn giải: "schema linh hoạt" đã bị hiểu nhầm thành "không cần kỷ luật dữ liệu". MongoDB không ép cấu trúc, nên trách nhiệm chuẩn hóa rơi hoàn toàn về phía con người — và đó chính là nơi BA phải đứng ra.

Bài học rút ra: Trong dự án dùng document DB, BA cần chủ động lập data dictionary quy định rõ tên trường chuẩn, kiểu dữ liệu, đơn vị, và các trường bắt buộc. Đồng thời đề xuất dùng cơ chế schema validation mà MongoDB hỗ trợ (đặt luật để chặn document sai cấu trúc ngay khi ghi). "Linh hoạt" nên là lựa chọn có chủ đích, không phải sự buông lỏng.

Tình huống 3 — App giao đồ ăn và quyết định nhúng hay tham chiếu

Một ứng dụng giao đồ ăn (giả định, kiểu GrabFood/ShopeeFood) lưu đơn hàng. BA và tech lead ngồi bàn: thông tin món ăn trong đơn nên nhúng vào document đơn hàng, hay tham chiếu tới collection menu?

Câu trả lời nghiêng về nhúng, vì một lý do nghiệp vụ rất quan trọng: giá và tên món tại thời điểm đặt hàng phải được "đóng băng". Nếu chỉ tham chiếu tới menu, hôm sau quán đổi giá phở từ 45.000 lên 50.000, thì hóa đơn cũ in ra sẽ hiển thị sai giá. Bằng cách nhúng snapshot món ăn (tên, giá, ghi chú) ngay trong document đơn hàng, lịch sử đơn được bảo toàn chính xác:

{ "_id": "DH9981", "khach": "KH00123", "mon": [
    { "ten": "Phở bò tái", "gia": 45000, "sl": 2 },
    { "ten": "Trà đá", "gia": 5000, "sl": 2 } ],
  "tong": 100000, "trang_thai": "da_giao" }

Diễn giải: đây là ví dụ kinh điển cho thấy quyết định nhúng/tham chiếu không thuần túy kỹ thuật mà gắn chặt với yêu cầu nghiệp vụ (tính bất biến của hóa đơn). BA là người mang yêu cầu nghiệp vụ này lên bàn để quyết định mô hình hóa đúng.

Bài học rút ra: Khi đặc tả dữ liệu, hãy luôn hỏi "dữ liệu này có cần giữ nguyên trạng tại thời điểm phát sinh không?". Nếu có, nhúng snapshot thường là lựa chọn đúng — và đây là kiểu quyết định mà document DB làm rất tự nhiên.

Hướng dẫn từng bước

Khi bạn là BA bước vào một dự án có dùng MongoDB / document database, đây là quy trình thực dụng để bạn làm chủ phần dữ liệu:

  • Xác nhận lựa chọn database và lý do. Hỏi thẳng đội kỹ thuật: "Vì sao chọn document DB cho phần này?". Câu trả lời tốt thường là dữ liệu không đồng nhất, hay đọc theo cụm, hoặc cần linh hoạt mở rộng thuộc tính. Nếu lý do mơ hồ, hãy ghi nhận như một rủi ro cần xem lại.
  • Liệt kê các thực thể nghiệp vụ và ánh xạ thành collection. Mỗi thực thể chính (khách hàng, đơn hàng, sản phẩm) thường tương ứng một collection. Viết ra danh sách này trong tài liệu.
  • Với mỗi collection, phác cấu trúc document mẫu. Dùng đúng cú pháp JSON để mô tả một document tiêu biểu, ghi rõ trường nào bắt buộc, trường nào tùy chọn, kiểu dữ liệu và đơn vị. Đây chính là data dictionary phiên bản document.
  • Quyết định nhúng hay tham chiếu cho từng quan hệ. Với mỗi cặp dữ liệu liên quan, đặt câu hỏi: hay đọc cùng nhau không? Có cần đóng băng theo thời điểm không? Dữ liệu con lớn hay nhỏ? Ghi rõ quyết định và lý do.
  • Định nghĩa luật xác thực (validation rules). Liệt kê các ràng buộc nghiệp vụ: trường bắt buộc, giá trị hợp lệ (ví dụ trang_thai chỉ nhận một số giá trị cố định), định dạng. Đề xuất đội dùng schema validation của MongoDB để thực thi.
  • Đối chiếu với yêu cầu báo cáo và truy vấn. Hỏi: "Sau này nghiệp vụ sẽ tìm kiếm, lọc, tổng hợp theo trường nào?". Điều này giúp đội biết cần đánh chỉ mục (index) ở đâu, tránh tình huống truy vấn chậm như bài học ở Tình huống 2.

Lỗi thường gặp & mẹo

Lỗi 1: Nghĩ "NoSQL nghĩa là không cần thiết kế dữ liệu". Đây là hiểu lầm tai hại nhất. Document DB chuyển trách nhiệm thiết kế từ database sang ứng dụng và sang BA. Mẹo: hãy coi việc viết data dictionary cho document là bắt buộc, không phải tùy chọn.

Lỗi 2: Bê nguyên tư duy bảng quan hệ sang document. Một số BA tách mọi thứ thành nhiều collection rồi "join" thủ công như SQL, làm mất hết ưu thế của document. Mẹo: học cách nghĩ theo "thực thể đọc cùng nhau thì gom vào một document".

Lỗi 3: Nhúng quá tay khiến document phình vô hạn. Ví dụ nhúng toàn bộ lịch sử bình luận của một bài viết vào chính bài viết đó — sau vài năm document nặng hàng megabyte, chậm và khó xử lý. Mẹo: dữ liệu tăng trưởng không giới hạn thì nên tham chiếu, không nhúng.

Lỗi 4: Quên rằng MongoDB cũng cần index. Nhiều người tưởng MongoDB "nhanh tự nhiên". Không có index, truy vấn lọc trên collection lớn vẫn chậm như thường. Mẹo: trong tài liệu, ghi rõ các trường thường dùng để lọc/tìm kiếm để đội đánh index.

Lỗi 5: Lẫn lộn MongoDB với mọi loại NoSQL. MongoDB là document DB; Redis là key-value; có loại column-family, graph... Mỗi loại hợp với bài toán khác nhau. Mẹo: khi nói chuyện, gọi đúng tên "document database" để tránh hiểu lầm.

Mẹo vàng cho BA: Khi mô tả dữ liệu document, luôn kèm một document mẫu thật bằng JSON trong tài liệu. Một ví dụ cụ thể giúp dev và tester hiểu nhanh hơn mười dòng mô tả trừu tượng.

Bài tập thực hành

  • Ánh xạ khái niệm: Cho một hệ thống quản lý phòng khám. Hãy liệt kê 3 collection bạn nghĩ là cần thiết, và với mỗi collection, viết một document mẫu bằng JSON (tối thiểu 4 trường, có ít nhất một trường lồng nhau hoặc một mảng).
  • Quyết định nhúng hay tham chiếu: Với hệ thống đặt vé xem phim, thông tin "ghế đã đặt" trong một đơn vé nên nhúng vào document đơn hay tham chiếu tới collection seats? Viết 3–4 câu lập luận dựa trên tiêu chí đọc-cùng-nhau và đóng-băng-theo-thời-điểm.
  • Phát hiện rủi ro dữ liệu: Cho collection transactions mà bạn thấy có document dùng trường amount, document khác dùng so_tien. Hãy viết 3 quy định cụ thể bạn sẽ đưa vào data dictionary để ngăn vấn đề này, và mô tả ngắn cách schema validation giúp thực thi.
  • Suy nghĩ ngược: Tìm một tình huống nghiệp vụ mà document database KHÔNG phải lựa chọn tốt, và giải thích vì sao (gợi ý: nghĩ về dữ liệu có nhiều quan hệ phức tạp, cần giao dịch chặt chẽ giữa nhiều bảng).

Tóm tắt

Document database, với MongoDB là đại diện phổ biến nhất, lưu dữ liệu dưới dạng document — mỗi document là một khối giống JSON chứa trọn vẹn thông tin một thực thể, và các document cùng loại được gom vào một collection (tương đương bảng). Document được lưu dạng nhị phân BSON để tối ưu hiệu năng. Điểm khác biệt lớn nhất là schema linh hoạt: các document không bắt buộc giống hệt cấu trúc, rất hợp với dữ liệu không đồng nhất như catalog sản phẩm đa chủng loại.

Với vai trò BA, ba điều cần nhớ. Một, "linh hoạt" không có nghĩa "không cần thiết kế" — trách nhiệm chuẩn hóa dữ liệu chuyển về phía bạn, nên data dictionary và validation rules càng quan trọng. Hai, quyết định nhúng (embed) hay tham chiếu (reference) là quyết định mô hình hóa cốt lõi, gắn chặt với yêu cầu nghiệp vụ như tính bất biến của hóa đơn. Ba, document DB không phải "viên đạn bạc" — với dữ liệu nhiều quan hệ phức tạp và giao dịch chặt chẽ, database quan hệ vẫn thường phù hợp hơn (chủ đề bạn sẽ đào sâu ở bài SQL vs NoSQL). Nắm vững những khái niệm này, bạn sẽ tự tin ngồi cùng đội kỹ thuật để thiết kế phần dữ liệu một cách đúng đắn ngay từ đầu.