Schemas trong Mongoose
Trong bài này chúng ta sẽ tìm hiểu về khái niệm Schemas trong Mongoose. Chắc hẳn trong bài trước các bạn cũng đã biết được Schemas được dùng để làm gì? Và cách sử dụng cơ bản của nó. Trong trường hợp bạn chưa hiểu rõ về khái niệm Schemas bạn có thể ghé thăm bài viết bước đầu làm quen với Mongoose. Trong bài này chúng mình sẽ cùng nhau đi tìm hiểu sâu hơn về nó.
1. Chỉ định một Schemas trong Mongoose
Để làm việc với Mongoose sau khi thực hiện connection thì chúng ta sẽ bắt đầu với một Schema. Mỗi Schemas đều được chỉ định tới một collection trong MongoDB và từ đó xác định hình "bộ khung" cho các document trong collection được chỉ đinh đó. Ở đây mình có một Schemas.
var mongoose = require("mongoose"); var Schema = mongoose.Schema; var blogSchema = new Schema({ title: String, // String is shorthand for {type: String} author: String, body: String, comments: [{ body: String, date: Date }], date: { type: Date, default: Date.now }, hidden: Boolean, meta: { votes: Number, favs: Number } });
Nếu bạn muốn thêm các giá trị mới cho Schema, hãy sử dụng phương thức Schema.add
blogSchema.add({ views: 'number', report: number'});
Mỗi key trong object truyền vào class new Schema
ví dụ như (title
, author
, body
,..) được chỉ định là một thuộc tính của một document, mỗi value trong object ( như trong ví dụ là String, Boolean, Number) sẽ đại diện cho kiểu dữ liệu được sử dụng ( SchemaType ). Trong ví dụ trên, chúng ta có thuộc tính title
, tất cả các giá trị của thuộc tính này sẽ được chuyển thành dạng chuỗi (String).
Bài viết này được đăng tại [free tuts .net]
Chúng ta có một số kiểu Schema (Schema Type) bao gồm :
- String
- Number
- Date
- Buffer
- Boolean
- Mixed
- ObjectId
- Array
- Decimal128
- Map
2. Khởi tạo một Model trong Mongoose
Để sử dụng được một Schema, chúng ta cần chuyển blogSchema
bên trên thành một Model mới có thể làm việc với nó. Để thực hiện chuyển đổi sử dụng cú pháp :
mongoose.model(modelName, Schema):
Ví dụ mình sẽ chuyển đổi Schema vừa khởi tạo bên trên thành Model như sau:
var mongoose = require("mongoose"); var Schema = mongoose.Schema; //Khai báo một Schema var blogSchema = new Schema({ title: String, // String is shorthand for {type: String} author: String, body: String, comments: [{ body: String, date: Date }], date: { type: Date, default: Date.now }, hidden: Boolean, meta: { votes: Number, favs: Number } }); //Thực hiện chuyển đổi từ Schema sang Model var Blog = mongoose.model('Blog', blogSchema);
3. Instance methods trong Mongoose
Khi một Model được khởi tạo, chúng ta có thể tạo ra các documents bằng Model. Các document có nhiều phương thức được xây dựng sẵn trong chúng. Ngoài ra, bạn có thể thêm các phương thức cho các documents.
Các method
có thể được chỉ định trong Schema để giúp thực hiện những việc liên quan đến Schema Document đó và giữ cho các đoạn code được tổ chức rõ ràng hơn.
// Khởi tạo một Schema var animalSchema = new Schema({ name: String, type: String }); // Gán một hàm cho object 'methods' của animalSchema animalSchema.methods.findSimilarTypes = function(cb) { return this.model("Animal").find({ type: this.type }, cb); };
Ngay bây giờ tất cả các document trong animal
sẽ bao gồm phương thức findSimilarTypes
trong chúng, bạn có thể gọi bất cứ lúc nào.
var Animal = mongoose.model('Animal', animalSchema); var dog = new Animal({ type: 'dog' }); dog.findSimilarTypes(function(err, dogs) { console.log(dogs); // woof });
Có một vài lưu ý khi sử dụng instance methods mà mongoose đưa ra như:
- Không nên ghi đè một document.
- Trong ví dụ trên mình sử dụng
Schema.methods
, ngoài ra còn có thể sử dụng phương thứcSchema.method()
để thay thế. Hai kết quả tra về như nhau. - Không chỉ định method bằng arrow function ( => {} ) trong ES6, bởi arrow function không hỗ trợ biến
this
4. Schema Statics trong Mongoose
Schema Statics được sử dụng để xử lý các tác vụ liên quan trực tiếp đến Model, khái niệm này khác với Instance methods ( xử lý các việc liên quan đến Schema document ). Chúng ta có thể thêm một Statics vào một Schema bằng cách thêm một function vào object schema's static
.
// Tạo một statics function bằng cách thêm một object animalSchema.statics.findByName = function(name) { return this.find({ name: new RegExp(name, "i") }); }; // hoặc thêm bằng cách gọi một hàm. animalSchema.static("findByBreed", function(breed) { return this.find({ breed }); }); const Animal = mongoose.model("Animal", animalSchema); let animals = await Animal.findByName("fido"); animls = animals.concat(await Animal.findByBreed("Poodle"));
5. Query Helper
Query Helpers là một phương thức giúp bạn có thể mở rộng các câu truy vấn của bạn, giống như là Instance method nhưng thay vào đó sử dụng cho các câu truy vấn. Chúng ta có một ví dụ như bên dưới:
animalSchema.query.byName = function(name) { return this.where({ name: new RegExp(name, 'i') }); }; var Animal = mongoose.model('Animal', animalSchema); Animal.find().byName('fido').exec(function(err, animals) { console.log(animals); }); Animal.findOne().byName('fido').exec(function(err, animal) { console.log(animal); });
6. Virtuals
Virtuals (ảo hóa) là một thuộc tính của một document mà chúng ta có thể làm việc mới một giá trị mà không cần thêm hay, lấy từ MongoDB. Nó rất hữu ích cho việc định dạng hoặc kết hợp các trường, trong khi đó lập trình viên rất dễ dàng có thể thực hiện việc kết hợp một giá trị thành nhiều giá trị để lưu trữ.
Ở đây mình tiến hành tạo một document có các trường như first, last :
// Chỉ định một Schema var personSchema = new Schema({ name: { first: String, last: String } }); // Đưa nó vào một Modal var Person = mongoose.model('Person', personSchema); // Tiến hành tạo môt document var axl = new Person({ name: { first: '', last: 'Rose' } });
Trong khi truy vấn bạn muốn in ra tên đầy đủ của một người thì thông thường sẽ sử dụng:
console.log(axl.name.first + ' ' + axl.name.last); // Nguyen Tri
Trong trường hợp bạn phải nối các chuỗi này nhiều lần thì chương trình sẽ khá cồng kềnh và khó quản lí, bởi vậy Mongoose cho phép chúng ta thêm các thuộc tính ảo hóa (Virtuals). Ví dụ, mình sẽ thêm một thuộc tính ảo cho Schame bên trên có tên là fullName :
personSchema.virtual('fullName').get(function () { return this.name.first + ' ' + this.name.last; });
Lúc này bạn có thể lấy tên đầy đủ của 1 người một cách nhanh chóng:
console.log(axl.fullName)
Trong bài viết này chúng ta đã tìm hiểu về Schemas trong Mongoose DB, rất mong bài viết này sẽ giúp ích cho bạn. Cảm ơn bạn đã ghé thăm bài viết.