MongoDB có thể không cần schema, nhưng điều đó không có nghĩa dữ liệu của bạn phải lộn xộn.
Trong bài viết này, bạn sẽ học mọi thứ từ những điều cơ bản về xác thực schema đến các trường hợp sử dụng nâng cao với toán tử $jsonSchema. Bạn sẽ khám phá cách áp đặt các trường bắt buộc, giới hạn kiểu dữ liệu, áp dụng mẫu (pattern) và xác thực tài liệu lồng nhau.
Chúng tôi cũng sẽ đề cập cách xác thực hoạt động trong khi chèn (insert) và cập nhật (update), cách sửa đổi các collection hiện có, và khi nào nên dùng các mức độ và hành động xác thực khác nhau.
Kết thúc bài viết, bạn sẽ tự tin áp dụng xác thực schema cho các collection MongoDB của mình, giữ cho dữ liệu sạch và có thể dự đoán, mà không phải từ bỏ sự linh hoạt vốn có của MongoDB. Bạn cũng có thể xem video về xác thực schema để tìm hiểu thêm.
Vì sao xác thực Schema quan trọng trong MongoDB
Mô hình tài liệu động của MongoDB mang lại tốc độ và tính linh hoạt bằng cách cho phép các tài liệu trong cùng một collection có các trường hoặc cấu trúc khác nhau. Đây là lợi thế lớn trong giai đoạn phát triển ban đầu hoặc khi cần lặp nhanh. Tuy nhiên, chính sự linh hoạt đó có thể nhanh chóng trở thành gánh nặng, dẫn đến dữ liệu không nhất quán, thiếu hoặc không hợp lệ khi ứng dụng của bạn phát triển.
Đó là lúc xác thực schema phát huy tác dụng. Nó cho phép bạn định nghĩa các quy tắc cho tài liệu của mình—chẳng hạn như các trường bắt buộc, kiểu dữ liệu cụ thể, hoặc cấu trúc lồng nhau—đồng thời vẫn tận dụng được tính linh hoạt của MongoDB.
Trong bài viết này, bạn sẽ học cách sử dụng toán tử mạnh mẽ $jsonSchema của MongoDB để áp dụng các quy tắc này cho collection. Dù bạn đang ngăn chặn các bản chèn sai định dạng trong một ứng dụng mới hay bổ sung quy tắc xác thực cho một cơ sở dữ liệu cũ, xác thực schema giúp đảm bảo dữ liệu sạch, truy vấn có thể dự đoán và ứng dụng ổn định.
Nếu bạn mới làm việc với MongoDB và Python, khóa học nhập môn MongoDB này là cách tuyệt vời để thực hành truy vấn và tích hợp trước khi đi sâu vào xác thực schema.
Trước khi bắt đầu
Để tận dụng tối đa hướng dẫn này, bạn cần có quyền truy cập vào một cụm MongoDB Atlas. Gói miễn phí là quá đủ để theo dõi.
Để các khái niệm rõ ràng và dễ áp dụng nhất, chúng tôi sẽ sửdụng bộ dữ liệu mẫu MongoDB Atlas—cụ thể là cơ sở dữ liệu sample_mflix. Bộ dữ liệu này gồm các collection như movies, comments, users và theaters, mà chúng tôi sẽ tham chiếu xuyên suốt bài viết để minh họa từng ví dụ. Bộ dữ liệu chứa các tài liệu với các trường như đối tượng lồng nhau, mảng, chuỗi, số và các trường tùy chọn.
Tải bộ dữ liệu mẫu (nếu cần)
1. Truy cập bảng điều khiển MongoDB Atlas của bạn.
2. Chọn cụm của bạn, nhấp nút “…” và chọn Load Sample Dataset.
3. Chờ vài phút cho đến khi cơ sở dữ liệu sample_mflix khả dụng.
Bắt đầu với xác thực Schema
Khi bộ dữ liệu đã được tải, hãy kết nối tới cụm của bạn bằng MongoDB Shell (mongosh) hoặc MongoDB Compass, sau đó chuyển sang bộ dữ liệu:
Dưới đây là phiên bản rút gọn của những gì bạn có thể thấy:
Hình 1. Truy vấn này dùng findOne() để truy xuất một tài liệu mẫu từ collection movies trong cơ sở dữ liệu sample_mflix. Kết quả hiển thị nhiều trường, gồm title, year, genres và các đối tượng lồng như imdb và tomatoes.viewer.
Tài liệu này chứa kết hợp các giá trị vô hướng, mảng và đối tượng lồng nhau, rất phù hợp để minh họa nhiều kỹ thuật xác thực. Ở phần tiếp theo, chúng ta sẽ tạo một collection mới dựa trên cấu trúc này và định nghĩa schema xác thực đầu tiên bằng $jsonSchema.
Từ khóa hỗ trợ, phần mở rộng và giới hạn
Xác thực $jsonSchema của MongoDB dựa trên đặc tả JSON Schema Draft 4, với một số điều chỉnh và lược bỏ. Dù không hỗ trợ tất cả tính năng từ đặc tả gốc, MongoDB bao gồm một tập con trọng tâm và thực tiễn, phù hợp để xác thực tài liệu BSON.
Dưới đây là một số từ khóa thường dùng nhất:
bsonType: Từ khóa kiểu dành riêng cho MongoDB (ví dụ: "string", "int", "array", "object")
required: Chỉ định các trường bắt buộc phải có
minimum/maximum: Cho xác thực khoảng giá trị số
pattern: Cho xác thực định dạng chuỗi bằng biểu thức chính quy
enum: Giới hạn một trường vào tập giá trị cho phép
items, minItems, maxItems: Cho xác thực mảng
properties: Định nghĩa quy tắc cho các trường bên trong một đối tượng
additionalProperties: Kiểm soát việc cho phép các trường thừa (chưa định nghĩa)
MongoDB cố ý lược bỏ một số tính năng nâng cao từ JSON Schema đầy đủ, như:
Trong bài viết này, chúng ta sẽ tập trung vào những từ khóa thực tiễn và được hỗ trợ rộng rãi nhất, đủ để bao quát các nhu cầu xác thực phổ biến trong thực tế mà không quá phức tạp.
Để hiểu rộng hơn về cách MongoDB phù hợp trong bức tranh NoSQL, hãy khám phá hướng dẫn toàn diện này.
Tạo collection với xác thực cơ bản
Giờ bạn đã thấy cấu trúc của một tài liệu movies, hãy tạo một collection mới áp đặt vài quy tắc cơ bản bằng $jsonSchema. Chúng ta sẽ bắt đầu với vài ràng buộc phổ biến:
title: phải là chuỗi và là bắt buộc
year: phải là số nguyên và là bắt buộc
genres: phải là mảng các chuỗi
runtime: phải là số nguyên dương
Chúng ta sẽ gọi collection mới này là validated_movies.
Tạo collection
Chạy lệnh sau để tạo collection với xác thực:
db.createCollection("validated_movies",{validator:{$jsonSchema:{bsonType:"object",required:["title","year","runtime"],properties:{title:{bsonType:"string",description:"must be a string and is required"},year:{bsonType:"int",minimum:1888,description:"must be an integer >= 1888 (year of the first film)"},runtime:{bsonType:"int",minimum:1,description:"must be a positive integer and is required"},genres:{bsonType:"array",items:{bsonType:"string"},description:"must be an array of strings"}}}},validationLevel:"strict",validationAction:"error"});Được hỗ trợ bởi
Chèn một tài liệu hợp lệ
Bây giờ, hãy chèn một tài liệu tuân theo schema:
db.validated_movies.insertOne({title:"Inception",year:2010,runtime:148,genres:["Action","Sci-Fi","Thriller"]});Được hỗ trợ bởi
✅ Thao tác này sẽ thành công.
Chèn một tài liệu không hợp lệ
Hãy thử chèn một tài liệu thiếu trường title:
db.validated_movies.insertOne({year:2020,runtime:95,genres:["Drama"]});Được hỗ trợ bởi
❌ Thao tác này sẽ thất bại với lỗi xác thực vì title là bắt buộc.
Hình 2. Lệnh đầu tiên chèn một tài liệu phim hợp lệ vào collection validated_movies, đáp ứng đầy đủ các trường và kiểu dữ liệu bắt buộc. Lệnh thứ hai cố gắng chèn tài liệu không có trường title bắt buộc, dẫn đến lỗi xác thực.
Làm việc với các collection hiện có
Bạn không cần bắt đầu từ đầu để dùng xác thực schema. MongoDB cho phép áp dụng quy tắc xác thực cho các collection hiện có bằng lệnh collMod. Điều này đặc biệt hữu ích khi bạn muốn thêm cấu trúc cho bộ dữ liệu cũ mà không ảnh hưởng tới các tài liệu hiện tại.
Trong phần này, chúng ta sẽ áp dụng một validator cho collection movies từ cơ sở dữ liệu sample_mflix.
Thêm validator với collMod
Hãy áp đặt một quy tắc cơ bản: Mỗi tài liệu phim phải có trường title kiểu chuỗi.
db.runCommand({collMod:"movies",validator:{$jsonSchema:{bsonType:"object",required:["title"],properties:{title:{bsonType:"string",description:"must be a string and is required"}}}},validationLevel:"moderate",validationAction:"warn"});Được hỗ trợ bởi
Kiểm tra các quy tắc xác thực trên collection
Sau khi sửa đổi collection movies bằng lệnh collMod, bạn có thể muốn xác nhận các quy tắc xác thực nào đang hoạt động.
Để kiểm tra validator schema hiện tại, chạy:
db.getCollectionInfos({name:"movies"})[0].options.validatorĐược hỗ trợ bởi
Lệnh này trả về đối tượng $jsonSchema định nghĩa các quy tắc xác thực trên collection. Đây là cách hữu ích để xác minh cấu hình của bạn đã được áp dụng đúng, đặc biệt sau khi chuyển chế độ như warn sang error, hoặc cập nhật cấu trúc các trường bắt buộc.
Tìm hiểu validationLevel và validationAction
validationLevel: "moderate": Chỉ xác thực các tài liệu đang được chèn hoặc cập nhật. Các tài liệu hiện có không khớp schema sẽ không gây lỗi.
validationAction: "warn": Thay vì từ chối các ghi không hợp lệ, MongoDB ghi lại cảnh báo. Hữu ích trong môi trường sản xuất khi bạn muốn giám sát vi phạm schema trước khi cưỡng chế.
Bạn sẽ thấy cảnh báo trong log, nhưng lệnh ghi vẫn thành công. Bạn có thể đổi action thành "error" sau này để cưỡng chế nghiêm ngặt khi đã tự tin.
Hình 3. Lệnh insertOne() thêm thành công một tài liệu vi phạm quy tắc schema vì validation action đặt là "warn." MongoDB chấp nhận ghi, nhưng thiếu trường title sẽ gây lỗi xác thực nếu "error" được áp dụng.
Xác thực tài liệu lồng nhau và mảng
Tài liệu MongoDB thường bao gồm các cấu trúc lồng nhau, như đối tượng trong đối tượng và mảng giá trị. May mắn thay, $jsonSchema hỗ trợ xác thực cả hai. Hãy khám phá cách áp dụng quy tắc cho tài liệu con và nội dung mảng bằng các trường từ collection movies.
Xác thực một tài liệu lồng nhau
Trong collection movies, mỗi tài liệu bao gồm một đối tượng nhúng imdb với các trường như rating, votes và id. Hãy áp đặt quy tắc đảm bảo rằng:
imdb là một đối tượng (nếu có).
imdb.rating là số trong khoảng 0 đến 10.
Bạn sẽ định nghĩa như sau:
db.createCollection("validated_nested",{validator:{$jsonSchema:{bsonType:"object",properties:{imdb:{bsonType:"object",properties:{rating:{bsonType:"double",minimum:0,maximum:10,description:"Must be a number between 0 and 10"}}}}}}});Được hỗ trợ bởi
Kiểm thử tài liệu lồng nhau
✅ Chèn hợp lệ:
db.validated_nested.insertOne({title:"Interstellar",imdb:{rating:8.6}});Được hỗ trợ bởi
❌ Chèn không hợp lệ (rating vượt phạm vi):
db.validated_nested.insertOne({title:"Bad Movie",imdb:{rating:12.5}});Được hỗ trợ bởi
Thao tác này sẽ báo lỗi xác thực vì rating lớn hơn 10. Hình 4. Thao tác chèn này thất bại vì trường rating bên trong đối tượng imdb lồng nhau vượt quá giá trị tối đa là 10 theo định nghĩa trong schema. MongoDB ném lỗi xác thực do vi phạm quy tắc $jsonSchema.
Xác thực mảng
Bạn cũng có thể áp đặt ràng buộc trên mảng. Giả sử bạn muốn đảm bảo rằng:
genres là mảng các chuỗi.
Mảng phải có ít nhất một phần tử.
Thêm phần này vào schema của bạn:
genres:{bsonType:"array",minItems:1,items:{bsonType:"string"},description:"Must be a non-empty array of strings"}Được hỗ trợ bởi
Kết hợp nhiều ràng buộc
Trong ứng dụng thực tế, tài liệu của bạn thường cần thỏa nhiều quy tắc xác thực cùng lúc—bao gồm trường bắt buộc, giá trị cho phép, kiểu và cấu trúc lồng nhau. Với $jsonSchema, bạn có thể dễ dàng kết hợp nhiều ràng buộc trong một định nghĩa schema duy nhất.
Hãy xây dựng một ví dụ đầy đủ hơn dựa trên cấu trúc tài liệu movies. Chúng ta sẽ áp đặt các quy tắc sau:
title: bắt buộc, phải là chuỗi
year: bắt buộc, số nguyên, ≥ 1888
rated: tùy chọn, nhưng phải khớp tập giá trị định sẵn
genres: phải là mảng không rỗng gồm các chuỗi
imdb.rating: số trong khoảng 0 đến 10
tomatoes.viewer.rating: tùy chọn, số trong khoảng 0 đến 5
Tạo một collection có xác thực đầy đủ
db.createCollection("validated_full",{validator:{$jsonSchema:{bsonType:"object",required:["title","year"],properties:{title:{bsonType:"string",description:"Title is required and must be a string"},year:{bsonType:"int",minimum:1888,description:"Year must be an integer >= 1888"},rated:{enum:["G","PG","PG-13","R","NC-17"],description:"Must be a valid MPAA rating"},genres:{bsonType:"array",minItems:1,items:{bsonType:"string"},description:"Must be a non-empty array of strings"},imdb:{bsonType:"object",properties:{rating:{bsonType:"double",minimum:0,maximum:10,description:"IMDB rating must be between 0 and 10"}}},tomatoes:{bsonType:"object",properties:{viewer:{bsonType:"object",properties:{rating:{bsonType:"double",minimum:0,maximum:5,description:"Viewer rating must be between 0 and 5"}}}}}}}}});Được hỗ trợ bởi
Chèn một tài liệu hợp lệ:
db.validated_full.insertOne({title:"The Matrix",year:1999,rated:"R",genres:["Action","Sci-Fi"],imdb:{rating:8.7},tomatoes:{viewer:{rating:4.2}}});Được hỗ trợ bởi
Chèn một tài liệu không hợp lệ:
db.validated_full.insertOne({title:"Untitled Project",year:2025,rated:"Unrated",genres:[],imdb:{rating:15},tomatoes:{viewer:{rating:6.1}}});Được hỗ trợ bởi
Thao tác này sẽ thất bại do:
Giá trị rated không hợp lệ.
Mảng genres rỗng.
imdb.rating vượt quá 10.
tomatoes.viewer.rating vượt quá 5.
Hình 5. Thao tác chèn này thất bại do nhiều vi phạm schema trong collection validated_full. Trường rated chứa giá trị không nằm trong enum cho phép, genres là mảng rỗng vi phạm quy tắc minItems, imdb.rating vượt mức tối đa 10 và sai kiểu, và tomatoes.viewer.rating vượt quá mức cho phép là 5. MongoDB từ chối thao tác chèn với lỗi xác thực chi tiết.
Giải thích các mức và hành động xác thực
MongoDB cung cấp khả năng kiểm soát chi tiết về cách và thời điểm áp dụng xác thực schema. Khi định nghĩa quy tắc xác thực, có hai tùy chọn ảnh hưởng đến hành vi cơ sở dữ liệu của bạn:
validationLevel: Thời điểm áp dụng quy tắc
validationAction: Điều gì xảy ra khi tài liệu không khớp quy tắc
validationLevel
Tùy chọn này kiểm soát thao tác nào sẽ bị ảnh hưởng bởi xác thực schema.
strict: Mọi chèn và cập nhật phải tuân thủ schema. Đây là chế độ mặc định và an toàn nhất.
moderate: Chỉ xác thực các tài liệu đang được chèn hoặc cập nhật. Các tài liệu hiện có, dù không hợp lệ, vẫn được giữ nguyên.
Khi nào dùng:
Dùng strict cho collection mới nơi bạn muốn cưỡng chế đầy đủ schema ngay từ đầu.
Dùng moderate khi áp dụng xác thực cho các collection đã chứa dữ liệu cũ hoặc thiếu cấu trúc.
validationAction
Tùy chọn này kiểm soát cách MongoDB phản hồi khi tài liệu vi phạm quy tắc xác thực.
error: Từ chối thao tác ghi và trả về lỗi xác thực.
warn: Chấp nhận ghi, nhưng ghi lại cảnh báo nội bộ trên máy chủ.
Quan trọng: Trên MongoDB Atlas, các cảnh báo từ warn không hiển thị với người dùng—bạn sẽ không thấy chúng trong giao diện hay log chuẩn.
Khi nào dùng:
Dùng warn trong phát triển hoặc khi triển khai dần để theo dõi vi phạm mà không chặn ghi.
Chuyển sang error khi bạn tự tin ứng dụng của mình ghi tài liệu hợp lệ và muốn cưỡng chế nghiêm ngặt schema.
Ví dụ: Chuyển từ Warn sang Error
Giả sử bạn bắt đầu với cấu hình này:
db.runCommand({collMod:"validated_full",validationAction:"warn",validationLevel:"moderate"});Được hỗ trợ bởi
Sau khi quan sát hành vi ứng dụng, bạn có thể chuyển sang cưỡng chế nghiêm ngặt:
db.runCommand({collMod:"validated_full",validationAction:"error",validationLevel:"strict"});Được hỗ trợ bởi
Hình 6. Hai lệnh collMod được dùng để sửa đổi hành vi xác thực của collection validated_full. Lệnh đầu đặt validationAction là "warn" và validationLevel là "moderate," cho phép chèn tài liệu không hợp lệ nhưng ghi cảnh báo nội bộ. Lệnh thứ hai chuyển sang cưỡng chế nghiêm ngặt bằng cách đặt validationAction là "error" và validationLevel là "strict," đảm bảo mọi chèn và cập nhật phải tuân thủ đầy đủ schema đã định nghĩa.
Giờ đây, mọi thao tác chèn hoặc cập nhật không hợp lệ sẽ bị chặn kèm thông báo lỗi.
Lỗi thường gặp và mẹo gỡ lỗi
Khi làm việc với xác thực schema, những sai sót nhỏ có thể dẫn đến lỗi khó hiểu—hoặc tệ hơn, tài liệu lách qua quy tắc mà không bị phát hiện. Dưới đây là một số vấn đề thường gặp và cách tránh:
Giá trị bsonType sai
Một trong những lỗi phổ biến khi dùng $jsonSchema là nhầm lẫn giữa kiểu JSON và “bsonType” của MongoDB. Trong khi "string" và "array" khá rõ ràng, các kiểu như số và boolean có thể gây nhầm.
Ví dụ:
Dùng "int" hoặc "long" cho số nguyên.
Dùng "double" cho số thực dấu phẩy động.
Dùng "bool" (không phải "boolean") cho giá trị đúng/sai.
Dùng "object" cho tài liệu con (không phải "dict" hay "map").
Dùng "array" cho danh sách.
Nếu bạn không chắc một trường được lưu dưới kiểu nào, bạn có thể kiểm tra tài liệu bằng typeof trong Mongo shell hoặc xem dữ liệu bằng MongoDB Compass.
Thiếu trường bắt buộc trong cập nhật từng phần
Khi dùng $set, xác thực chỉ kiểm tra các trường được sửa đổi. Nếu bạn kỳ vọng kiểm tra toàn bộ schema, hãy thay thế toàn bộ tài liệu hoặc dùng validationLevel: "strict" kèm logic ứng dụng cưỡng chế đầy đủ cấu trúc.
Mảng rỗng vẫn vượt qua khi không nên
Nếu bạn quên chỉ định minItems, một mảng rỗng sẽ vượt qua:
genres:{bsonType:"array",items:{bsonType:"string"}}// Accepts empty arrays by defaultĐược hỗ trợ bởi
Hãy dùng minItems: 1 để đảm bảo có ít nhất một giá trị.
Không có lỗi khi ở chế độ warn
Như đã đề cập, validationAction: "warn" không chặn ghi hay hiển thị lỗi trên MongoDB Atlas. Nó chỉ ghi log nội bộ, vì vậy xác thực có thể có vẻ như “không hoạt động.”
Hãy dùng chế độ "error" trong phát triển hoặc môi trường thử nghiệm để phát hiện vấn đề sớm.
Đường dẫn trường lồng nhau không được kiểm tra nếu thiếu đối tượng cha
Nếu imdb.rating là bắt buộc, nhưng imdb hoàn toàn thiếu, MongoDB sẽ không kiểm tra rating.
Để cưỡng chế xác thực trên các trường lồng nhau, hãy đảm bảo đối tượng cha của chúng hoặc là bắt buộc, hoặc có bsonType: "object".
Truy vấn hoặc cập nhật các tài liệu không khớp schema
Sau khi áp dụng xác thực cho một collection hiện có, việc xác định các tài liệu không tuân theo schema mới thường rất hữu ích. Bạn có thể làm điều này bằng cách dùng toán tử $jsonSchema trong truy vấn với $nor hoặc $not.
Ví dụ: Tìm tài liệu không hợp lệ trong collection movies
Giả sử schema của bạn yêu cầu title kiểu "string." Để tìm các tài liệu không khớp, bạn có thể chạy:
db.movies.find({$nor:[{$jsonSchema:{bsonType:"object",required:["title"],properties:{title:{bsonType:"string"}}}}]});Được hỗ trợ bởi
Lệnh này sẽ trả về các tài liệu thiếu title hoặc có title sai kiểu.
Hình 7. Truy vấn này dùng $nor với $jsonSchema để tìm các tài liệu trong collection movies không có trường title kiểu string. Kết quả hiển thị một tài liệu với _id: 683ce0050bd195c35e417534 chỉ chứa trường year, xác nhận rằng nó vi phạm schema yêu cầu title. Kỹ thuật này hữu ích để xác định tài liệu không hợp lệ trước khi áp dụng xác thực nghiêm ngặt hơn.
Bạn cũng có thể dùng cách tiếp cận này để:
Kiểm toán các tài liệu cũ trước khi chuyển từ "warn" sang "error."
Làm sạch hoặc sửa tài liệu không hợp lệ bằng chương trình.
Tạo báo cáo về mức độ tuân thủ schema.
Tổng kết: Dữ liệu sạch mà không hy sinh tính linh hoạt
Thiết kế không cần schema của MongoDB là một trong những thế mạnh lớn nhất, nhưng điều đó không có nghĩa bạn nên để dữ liệu không được kiểm soát. Với $jsonSchema, bạn có thể định nghĩa các quy tắc xác thực mạnh mẽ để áp đặt cấu trúc trong khi vẫn tận dụng tính linh hoạt của MongoDB.
Xuyên suốt bài viết, bạn đã học cách:
Tạo collection với quy tắc xác thực.
Áp dụng ràng buộc cho collection mới và hiện có.
Dùng xác thực lồng cho đối tượng và mảng.
Cấu hình chế độ và hành động xác thực.
Gỡ lỗi và tinh chỉnh schema một cách tự tin.
Dù bạn xây dựng ứng dụng mới hoàn toàn hay bổ sung cấu trúc cho hệ thống cũ, xác thực schema cho bạn công cụ để bảo vệ dữ liệu mà không làm chậm phát triển.
Bước tiếp theo và tài nguyên
Muốn tìm hiểu sâu hơn? Hãy xem các tài nguyên này:
Đang chuẩn bị phỏng vấn? Những câu hỏi MongoDB hàng đầu này sẽ kiểm tra hiểu biết của bạn về các chủ đề như xác thực schema và nhiều hơn nữa. Muốn xác thực kỹ năng của bạn? Hướng dẫn chứng chỉ này phác thhọa mọi thứ bạn cần biết để được chứng nhận MongoDB.
Hãy nhớ, bắt đầu từ nhỏ, thử với "warn," và chuyển sang "error" khi bạn đã tự tin—bản thân bạn trong tương lai (và dữ liệu của bạn) sẽ biết ơn điều đó.
Câu hỏi thường gặp
Xác thực schema tương tác thế nào với cập nhật từng phần bằng $set?⌄
Khi bạn thực hiện cập nhật bằng các toán tử như $set, MongoDB chỉ xác thực các trường được sửa đổi—không phải toàn bộ tài liệu—trừ khi bạn dùng validationLevel: "strict" và cập nhật thay thế toàn bộ tài liệu. Để đảm bảo xác thực toàn phần, bạn có thể dùng thay thế tài liệu hoặc cưỡng chế cấu trúc ở tầng ứng dụng.
Tôi có thể ép buộc một trường chỉ tồn tại nếu trường khác có mặt không?⌄
Không trực tiếp. $jsonSchema của MongoDB không hỗ trợ xác thực có điều kiện (if/then/else). Tuy nhiên, đôi khi bạn có thể xấp xỉ điều này với xác thực dựa trên biểu thức (ví dụ, dùng $expr với $cond) hoặc kết hợp $jsonSchema với một lớp bọc $and. Với logic phức tạp hơn, hãy xử lý ở ứng dụng.
Các quy tắc xác thực được đánh giá trước hay sau các giá trị mặc định hoặc chuyển đổi của schema?⌄
MongoDB không áp dụng giá trị mặc định hoặc chuyển đổi trường ở cấp cơ sở dữ liệu. Xác thực được áp dụng chính xác như tài liệu được gửi đến. Mọi giá trị mặc định, ép kiểu, hoặc chuyển đổi phải được xử lý bởi logic ứng dụng trước khi ghi vào cơ sở dữ liệu.
Tôi có thể quản lý phiên bản hoặc phát triển schema theo thời gian mà không làm hỏng dữ liệu cũ không?⌄
Có. Một chiến lược phổ biến là dùng validationLevel: "moderate" trong khi dần dần áp dụng các quy tắc nghiêm ngặt hơn. Bạn cũng có thể gắn thẻ tài liệu với trường schemaVersion và áp dụng logic có điều kiện trong ứng dụng. MongoDB không cung cấp tính năng quản lý phiên bản schema tích hợp, vì vậy việc kiểm soát phiên bản phải được quản lý bên ngoài.
Xác thực schema có ảnh hưởng đến hiệu năng khi chèn và cập nhật không?⌄
Có tác động nhỏ—nhưng thường không đáng kể trong đa số ứng dụng. Xác thực tạo ra một chút chi phí cho mỗi thao tác ghi, nhưng nó có thể ngăn những vấn đề tốn kém hơn nhiều sau này bằng cách từ chối dữ liệu không hợp lệ sớm. Nếu bạn xác thực sâu các tài liệu lồng nhau hoặc rất lớn, hãy đo kiểm hiệu năng phù hợp.
MongoDB có thể không cần schema, nhưng điều đó không có nghĩa dữ liệu của bạn phải lộn xộn.
Trong bài viết này, bạn sẽ học mọi thứ từ những điều cơ bản về xác thực schema đến các trường hợp sử dụng nâng cao với toán tử
$jsonSchema. Bạn sẽ khám phá cách áp đặt các trường bắt buộc, giới hạn kiểu dữ liệu, áp dụng mẫu (pattern) và xác thực tài liệu lồng nhau.Chúng tôi cũng sẽ đề cập cách xác thực hoạt động trong khi chèn (insert) và cập nhật (update), cách sửa đổi các collection hiện có, và khi nào nên dùng các mức độ và hành động xác thực khác nhau.
Kết thúc bài viết, bạn sẽ tự tin áp dụng xác thực schema cho các collection MongoDB của mình, giữ cho dữ liệu sạch và có thể dự đoán, mà không phải từ bỏ sự linh hoạt vốn có của MongoDB. Bạn cũng có thể xem video về xác thực schema để tìm hiểu thêm.
Vì sao xác thực Schema quan trọng trong MongoDB
Mô hình tài liệu động của MongoDB mang lại tốc độ và tính linh hoạt bằng cách cho phép các tài liệu trong cùng một collection có các trường hoặc cấu trúc khác nhau. Đây là lợi thế lớn trong giai đoạn phát triển ban đầu hoặc khi cần lặp nhanh. Tuy nhiên, chính sự linh hoạt đó có thể nhanh chóng trở thành gánh nặng, dẫn đến dữ liệu không nhất quán, thiếu hoặc không hợp lệ khi ứng dụng của bạn phát triển.
Đó là lúc xác thực schema phát huy tác dụng. Nó cho phép bạn định nghĩa các quy tắc cho tài liệu của mình—chẳng hạn như các trường bắt buộc, kiểu dữ liệu cụ thể, hoặc cấu trúc lồng nhau—đồng thời vẫn tận dụng được tính linh hoạt của MongoDB.
Trong bài viết này, bạn sẽ học cách sử dụng toán tử mạnh mẽ
$jsonSchemacủa MongoDB để áp dụng các quy tắc này cho collection. Dù bạn đang ngăn chặn các bản chèn sai định dạng trong một ứng dụng mới hay bổ sung quy tắc xác thực cho một cơ sở dữ liệu cũ, xác thực schema giúp đảm bảo dữ liệu sạch, truy vấn có thể dự đoán và ứng dụng ổn định.Nếu bạn mới làm việc với MongoDB và Python, khóa học nhập môn MongoDB này là cách tuyệt vời để thực hành truy vấn và tích hợp trước khi đi sâu vào xác thực schema.
Trước khi bắt đầu
Để tận dụng tối đa hướng dẫn này, bạn cần có quyền truy cập vào một cụm MongoDB Atlas. Gói miễn phí là quá đủ để theo dõi.
Để các khái niệm rõ ràng và dễ áp dụng nhất, chúng tôi sẽ sửdụng bộ dữ liệu mẫu MongoDB Atlas—cụ thể là cơ sở dữ liệu
sample_mflix. Bộ dữ liệu này gồm các collection như movies, comments, users và theaters, mà chúng tôi sẽ tham chiếu xuyên suốt bài viết để minh họa từng ví dụ. Bộ dữ liệu chứa các tài liệu với các trường như đối tượng lồng nhau, mảng, chuỗi, số và các trường tùy chọn.Tải bộ dữ liệu mẫu (nếu cần)
1. Truy cập bảng điều khiển MongoDB Atlas của bạn.
2. Chọn cụm của bạn, nhấp nút “…” và chọn Load Sample Dataset.
3. Chờ vài phút cho đến khi cơ sở dữ liệu sample_mflix khả dụng.
Bắt đầu với xác thực Schema
Khi bộ dữ liệu đã được tải, hãy kết nối tới cụm của bạn bằng MongoDB Shell (mongosh) hoặc MongoDB Compass, sau đó chuyển sang bộ dữ liệu:
Khám phá bộ dữ liệu với findOne()
Hãy kiểm tra một trong các tài liệu từ collection movies:
Dưới đây là phiên bản rút gọn của những gì bạn có thể thấy:
Hình 1. Truy vấn này dùng findOne() để truy xuất một tài liệu mẫu từ collection movies trong cơ sở dữ liệu sample_mflix. Kết quả hiển thị nhiều trường, gồm title, year, genres và các đối tượng lồng như imdb và tomatoes.viewer.
Tài liệu này chứa kết hợp các giá trị vô hướng, mảng và đối tượng lồng nhau, rất phù hợp để minh họa nhiều kỹ thuật xác thực. Ở phần tiếp theo, chúng ta sẽ tạo một collection mới dựa trên cấu trúc này và định nghĩa schema xác thực đầu tiên bằng
$jsonSchema.Từ khóa hỗ trợ, phần mở rộng và giới hạn
Xác thực
$jsonSchemacủa MongoDB dựa trên đặc tả JSON Schema Draft 4, với một số điều chỉnh và lược bỏ. Dù không hỗ trợ tất cả tính năng từ đặc tả gốc, MongoDB bao gồm một tập con trọng tâm và thực tiễn, phù hợp để xác thực tài liệu BSON.Dưới đây là một số từ khóa thường dùng nhất:
MongoDB cố ý lược bỏ một số tính năng nâng cao từ JSON Schema đầy đủ, như:
Để xem danh sách đầy đủ các tùy chọn được hỗ trợ, hãy xem tài liệu chính thức về MongoDB $jsonSchema.
Trong bài viết này, chúng ta sẽ tập trung vào những từ khóa thực tiễn và được hỗ trợ rộng rãi nhất, đủ để bao quát các nhu cầu xác thực phổ biến trong thực tế mà không quá phức tạp.
Để hiểu rộng hơn về cách MongoDB phù hợp trong bức tranh NoSQL, hãy khám phá hướng dẫn toàn diện này.
Tạo collection với xác thực cơ bản
Giờ bạn đã thấy cấu trúc của một tài liệu movies, hãy tạo một collection mới áp đặt vài quy tắc cơ bản bằng
$jsonSchema. Chúng ta sẽ bắt đầu với vài ràng buộc phổ biến:Chúng ta sẽ gọi collection mới này là
validated_movies.Tạo collection
Chạy lệnh sau để tạo collection với xác thực:
Chèn một tài liệu hợp lệ
Bây giờ, hãy chèn một tài liệu tuân theo schema:
✅ Thao tác này sẽ thành công.
Chèn một tài liệu không hợp lệ
Hãy thử chèn một tài liệu thiếu trường
title:❌ Thao tác này sẽ thất bại với lỗi xác thực vì
titlelà bắt buộc.Hình 2. Lệnh đầu tiên chèn một tài liệu phim hợp lệ vào collection validated_movies, đáp ứng đầy đủ các trường và kiểu dữ liệu bắt buộc. Lệnh thứ hai cố gắng chèn tài liệu không có trường title bắt buộc, dẫn đến lỗi xác thực.
Làm việc với các collection hiện có
Bạn không cần bắt đầu từ đầu để dùng xác thực schema. MongoDB cho phép áp dụng quy tắc xác thực cho các collection hiện có bằng lệnh
collMod. Điều này đặc biệt hữu ích khi bạn muốn thêm cấu trúc cho bộ dữ liệu cũ mà không ảnh hưởng tới các tài liệu hiện tại.Trong phần này, chúng ta sẽ áp dụng một validator cho collection movies từ cơ sở dữ liệu
sample_mflix.Thêm validator với collMod
Hãy áp đặt một quy tắc cơ bản: Mỗi tài liệu phim phải có trường
titlekiểu chuỗi.Kiểm tra các quy tắc xác thực trên collection
Sau khi sửa đổi collection
moviesbằng lệnhcollMod, bạn có thể muốn xác nhận các quy tắc xác thực nào đang hoạt động.Để kiểm tra validator schema hiện tại, chạy:
Lệnh này trả về đối tượng
$jsonSchemađịnh nghĩa các quy tắc xác thực trên collection. Đây là cách hữu ích để xác minh cấu hình của bạn đã được áp dụng đúng, đặc biệt sau khi chuyển chế độ như warn sang error, hoặc cập nhật cấu trúc các trường bắt buộc.Tìm hiểu validationLevel và validationAction
Hãy thử chèn một tài liệu vi phạm schema:
Bạn sẽ thấy cảnh báo trong log, nhưng lệnh ghi vẫn thành công. Bạn có thể đổi action thành "error" sau này để cưỡng chế nghiêm ngặt khi đã tự tin.
Hình 3. Lệnh insertOne() thêm thành công một tài liệu vi phạm quy tắc schema vì validation action đặt là "warn." MongoDB chấp nhận ghi, nhưng thiếu trường title sẽ gây lỗi xác thực nếu "error" được áp dụng.
Xác thực tài liệu lồng nhau và mảng
Tài liệu MongoDB thường bao gồm các cấu trúc lồng nhau, như đối tượng trong đối tượng và mảng giá trị. May mắn thay,
$jsonSchemahỗ trợ xác thực cả hai. Hãy khám phá cách áp dụng quy tắc cho tài liệu con và nội dung mảng bằng các trường từ collection movies.Xác thực một tài liệu lồng nhau
Trong collection movies, mỗi tài liệu bao gồm một đối tượng nhúng
imdbvới các trường nhưrating,votesvàid. Hãy áp đặt quy tắc đảm bảo rằng:imdblà một đối tượng (nếu có).imdb.ratinglà số trong khoảng 0 đến 10.Bạn sẽ định nghĩa như sau:
Kiểm thử tài liệu lồng nhau
✅ Chèn hợp lệ:
❌ Chèn không hợp lệ (rating vượt phạm vi):
Thao tác này sẽ báo lỗi xác thực vì rating lớn hơn 10.
Hình 4. Thao tác chèn này thất bại vì trường rating bên trong đối tượng imdb lồng nhau vượt quá giá trị tối đa là 10 theo định nghĩa trong schema. MongoDB ném lỗi xác thực do vi phạm quy tắc $jsonSchema.
Xác thực mảng
Bạn cũng có thể áp đặt ràng buộc trên mảng. Giả sử bạn muốn đảm bảo rằng:
genreslà mảng các chuỗi.Thêm phần này vào schema của bạn:
Kết hợp nhiều ràng buộc
Trong ứng dụng thực tế, tài liệu của bạn thường cần thỏa nhiều quy tắc xác thực cùng lúc—bao gồm trường bắt buộc, giá trị cho phép, kiểu và cấu trúc lồng nhau. Với
$jsonSchema, bạn có thể dễ dàng kết hợp nhiều ràng buộc trong một định nghĩa schema duy nhất.Hãy xây dựng một ví dụ đầy đủ hơn dựa trên cấu trúc tài liệu movies. Chúng ta sẽ áp đặt các quy tắc sau:
Tạo một collection có xác thực đầy đủ
Chèn một tài liệu hợp lệ:
Chèn một tài liệu không hợp lệ:
Thao tác này sẽ thất bại do:
ratedkhông hợp lệ.genresrỗng.imdb.ratingvượt quá 10.tomatoes.viewer.ratingvượt quá 5.Hình 5. Thao tác chèn này thất bại do nhiều vi phạm schema trong collection validated_full. Trường rated chứa giá trị không nằm trong enum cho phép, genres là mảng rỗng vi phạm quy tắc minItems, imdb.rating vượt mức tối đa 10 và sai kiểu, và tomatoes.viewer.rating vượt quá mức cho phép là 5. MongoDB từ chối thao tác chèn với lỗi xác thực chi tiết.
Giải thích các mức và hành động xác thực
MongoDB cung cấp khả năng kiểm soát chi tiết về cách và thời điểm áp dụng xác thực schema. Khi định nghĩa quy tắc xác thực, có hai tùy chọn ảnh hưởng đến hành vi cơ sở dữ liệu của bạn:
validationLevel
Tùy chọn này kiểm soát thao tác nào sẽ bị ảnh hưởng bởi xác thực schema.
Khi nào dùng:
validationAction
Tùy chọn này kiểm soát cách MongoDB phản hồi khi tài liệu vi phạm quy tắc xác thực.
Quan trọng: Trên MongoDB Atlas, các cảnh báo từ warn không hiển thị với người dùng—bạn sẽ không thấy chúng trong giao diện hay log chuẩn.
Khi nào dùng:
Ví dụ: Chuyển từ Warn sang Error
Giả sử bạn bắt đầu với cấu hình này:
Sau khi quan sát hành vi ứng dụng, bạn có thể chuyển sang cưỡng chế nghiêm ngặt:
Hình 6. Hai lệnh collMod được dùng để sửa đổi hành vi xác thực của collection validated_full. Lệnh đầu đặt validationAction là "warn" và validationLevel là "moderate," cho phép chèn tài liệu không hợp lệ nhưng ghi cảnh báo nội bộ. Lệnh thứ hai chuyển sang cưỡng chế nghiêm ngặt bằng cách đặt validationAction là "error" và validationLevel là "strict," đảm bảo mọi chèn và cập nhật phải tuân thủ đầy đủ schema đã định nghĩa.
Giờ đây, mọi thao tác chèn hoặc cập nhật không hợp lệ sẽ bị chặn kèm thông báo lỗi.
Lỗi thường gặp và mẹo gỡ lỗi
Khi làm việc với xác thực schema, những sai sót nhỏ có thể dẫn đến lỗi khó hiểu—hoặc tệ hơn, tài liệu lách qua quy tắc mà không bị phát hiện. Dưới đây là một số vấn đề thường gặp và cách tránh:
Giá trị bsonType sai
Một trong những lỗi phổ biến khi dùng
$jsonSchemalà nhầm lẫn giữa kiểu JSON và “bsonType” của MongoDB. Trong khi "string" và "array" khá rõ ràng, các kiểu như số và boolean có thể gây nhầm.Ví dụ:
Nếu bạn không chắc một trường được lưu dưới kiểu nào, bạn có thể kiểm tra tài liệu bằng typeof trong Mongo shell hoặc xem dữ liệu bằng MongoDB Compass.
Thiếu trường bắt buộc trong cập nhật từng phần
Khi dùng
$set, xác thực chỉ kiểm tra các trường được sửa đổi. Nếu bạn kỳ vọng kiểm tra toàn bộ schema, hãy thay thế toàn bộ tài liệu hoặc dùngvalidationLevel: "strict"kèm logic ứng dụng cưỡng chế đầy đủ cấu trúc.Mảng rỗng vẫn vượt qua khi không nên
Nếu bạn quên chỉ định
minItems, một mảng rỗng sẽ vượt qua:Hãy dùng
minItems: 1để đảm bảo có ít nhất một giá trị.Không có lỗi khi ở chế độ warn
Như đã đề cập,
validationAction: "warn"không chặn ghi hay hiển thị lỗi trên MongoDB Atlas. Nó chỉ ghi log nội bộ, vì vậy xác thực có thể có vẻ như “không hoạt động.”Hãy dùng chế độ "error" trong phát triển hoặc môi trường thử nghiệm để phát hiện vấn đề sớm.
Đường dẫn trường lồng nhau không được kiểm tra nếu thiếu đối tượng cha
Nếu
imdb.ratinglà bắt buộc, nhưngimdbhoàn toàn thiếu, MongoDB sẽ không kiểm trarating.Để cưỡng chế xác thực trên các trường lồng nhau, hãy đảm bảo đối tượng cha của chúng hoặc là bắt buộc, hoặc có
bsonType: "object".Truy vấn hoặc cập nhật các tài liệu không khớp schema
Sau khi áp dụng xác thực cho một collection hiện có, việc xác định các tài liệu không tuân theo schema mới thường rất hữu ích. Bạn có thể làm điều này bằng cách dùng toán tử
$jsonSchematrong truy vấn với$norhoặc$not.Ví dụ: Tìm tài liệu không hợp lệ trong collection movies
Giả sử schema của bạn yêu cầu title kiểu "string." Để tìm các tài liệu không khớp, bạn có thể chạy:
Lệnh này sẽ trả về các tài liệu thiếu title hoặc có title sai kiểu.
Hình 7. Truy vấn này dùng $nor với $jsonSchema để tìm các tài liệu trong collection movies không có trường title kiểu string. Kết quả hiển thị một tài liệu với _id: 683ce0050bd195c35e417534 chỉ chứa trường year, xác nhận rằng nó vi phạm schema yêu cầu title. Kỹ thuật này hữu ích để xác định tài liệu không hợp lệ trước khi áp dụng xác thực nghiêm ngặt hơn.
Bạn cũng có thể dùng cách tiếp cận này để:
Tổng kết: Dữ liệu sạch mà không hy sinh tính linh hoạt
Thiết kế không cần schema của MongoDB là một trong những thế mạnh lớn nhất, nhưng điều đó không có nghĩa bạn nên để dữ liệu không được kiểm soát. Với
$jsonSchema, bạn có thể định nghĩa các quy tắc xác thực mạnh mẽ để áp đặt cấu trúc trong khi vẫn tận dụng tính linh hoạt của MongoDB.Xuyên suốt bài viết, bạn đã học cách:
Dù bạn xây dựng ứng dụng mới hoàn toàn hay bổ sung cấu trúc cho hệ thống cũ, xác thực schema cho bạn công cụ để bảo vệ dữ liệu mà không làm chậm phát triển.
Bước tiếp theo và tài nguyên
Muốn tìm hiểu sâu hơn? Hãy xem các tài nguyên này:
Đang chuẩn bị phỏng vấn? Những câu hỏi MongoDB hàng đầu này sẽ kiểm tra hiểu biết của bạn về các chủ đề như xác thực schema và nhiều hơn nữa. Muốn xác thực kỹ năng của bạn? Hướng dẫn chứng chỉ này phác thhọa mọi thứ bạn cần biết để được chứng nhận MongoDB.
Hãy nhớ, bắt đầu từ nhỏ, thử với "warn," và chuyển sang "error" khi bạn đã tự tin—bản thân bạn trong tương lai (và dữ liệu của bạn) sẽ biết ơn điều đó.