06/04/2021, 14:50

Schemas trong Mongoose - NodeJS căn bản

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 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).

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 methodsmongoose đư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ức Schema.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.

Hoàng Hải Đăng

24 chủ đề

7226 bài viết

Cùng chủ đề
0