0
0
Lập trình
Admin Team
Admin Teamtechmely

Hướng Dẫn Viết Code Hiệu Quả Hơn Với Mongoose Schemas

Đăng vào 1 tháng trước

• 4 phút đọc

Nếu bạn là một nhà phát triển đã quen thuộc với việc xây dựng các ứng dụng NodeJS bằng Mongoose ORM, thì bài viết này sẽ là nguồn tài liệu hữu ích cho bạn. Chúng ta sẽ khám phá một số tính năng mạnh mẽ của Mongoose Schemas có thể giúp bạn tổ chức mã nguồn một cách hợp lý và dễ bảo trì.

Mongoose Schema Là Gì?

Mongoose Schema cung cấp một cách có cấu trúc để mô hình hóa dữ liệu trong cơ sở dữ liệu MongoDB. Thông qua schema, bạn có thể xác định các thuộc tính và hành vi cho các tài liệu. Schema hoạt động như một bản thiết kế cho tài liệu được lưu trữ trong cơ sở dữ liệu, giúp các nhà phát triển duy trì tính toàn vẹn của dữ liệu và làm việc với MongoDB một cách trực quan hơn.

Trong một bộ sưu tập MongoDB, schema mô tả các trường tài liệu, kiểu dữ liệu của chúng, quy tắc xác thực, giá trị mặc định, và nhiều yếu tố khác. Về mặt lập trình, Mongoose Schemas là một đối tượng JavaScript, và bạn có thể mở rộng nó với nhiều phương thức khác nhau. Điều này sẽ cho phép bạn triển khai nhiều tính năng như middleware, phương thức statics, và hơn thế nữa. Bài viết này sẽ hướng dẫn bạn về một số trong số chúng.

Tính Năng Discriminator

Discriminator là một tính năng mạnh mẽ, cho phép bạn tạo nhiều mô hình (subtypes) kế thừa từ một mô hình cơ sở (parent). Bằng cách định nghĩa một schema cơ bản và sau đó mở rộng nó với các trường bổ sung cho mỗi subtype, bạn có thể giữ cho dữ liệu của mình được tổ chức mà không cần phân tán qua nhiều bộ sưu tập.

Hướng Dẫn Sử Dụng Discriminator:

  1. Định nghĩa một schema cơ bản với các trường chung giữa các subtype:

    javascript Copy
    import mongoose from 'mongoose';
    const baseSchema = new mongoose.Schema({
        name: { type: String, required: true },
    }, { discriminatorKey: 'kind' });
    const BaseModel = mongoose.model('Base', baseSchema);
  2. Tạo các subtype mở rộng schema cơ bản bằng discriminator:

    javascript Copy
    const catSchema = new mongoose.Schema({
        meow: { type: Boolean, default: true }
    });
    const Cat = BaseModel.discriminator('Cat', catSchema);
    
    const dogSchema = new mongoose.Schema({
        bark: { type: Boolean, default: true }
    });
    const Dog = BaseModel.discriminator('Dog', dogSchema);
  3. Tạo tài liệu như bình thường:

    javascript Copy
    const fluffy = await Cat.create({ name: 'Fluffy' });
    const rover = await Dog.create({ name: 'Rover' });

Ví Dụ Về Ứng Dụng Discriminator

Giả sử bạn đang xây dựng một ứng dụng thương mại điện tử với ba vai trò người dùng: quản trị viên, khách hàng và người bán. Bạn có thể tạo một schema cha cho người dùng và sau đó sử dụng discriminator để tạo các subtype cho từng vai trò.

javascript Copy
// user.model.js
import mongoose from "mongoose";
const userSchema = mongoose.Schema({
  name: String,
  profilePic: String,
  email: String,
  password: String,
  birthDate: Date,
  accountActivated: { type: Boolean, default: false },
}, {
  timestamps: true,
  discriminatorKey: "role",
});
const User = mongoose.model("User", userSchema);
export default User;

Tiếp tục, bạn sẽ tạo các model cho từng vai trò (client, seller, admin) ở các file khác nhau và mở rộng từ mô hình User. Dù tất cả tài liệu được lưu trữ trong cùng một bộ sưu tập, nhưng bạn vẫn có thể truy vấn riêng biệt cho từng loại người dùng.

Tính Năng Statics

Statics giúp bạn định nghĩa các hàm tái sử dụng cho các hoạt động liên quan đến toàn bộ mô hình. Chúng cho phép đóng gói logic áp dụng cho mô hình, làm cho mã nguồn của bạn gọn gàng hơn.

Ví dụ, bạn có thể định nghĩa phương thức static để đếm số lượng người dùng:

javascript Copy
userSchema.statics.countUsers = function () {
    return this.countDocuments({});
};

Tính Năng Methods

Methods là các hàm được định nghĩa trên schema và có thể được gọi trên các đối tượng tài liệu. Chúng giúp đóng gói logic bên trong từng tài liệu và dễ dàng thao tác với chúng.

Ví dụ, bạn có thể định nghĩa một phương thức để kiểm tra mật khẩu:

javascript Copy
userSchema.methods.checkPassword = function (password) {
    return password === this.password;
};

Trình Xây Dựng Truy Vấn

Mongoose cho phép bạn định nghĩa các trình xây dựng truy vấn để đơn giản hóa các mô hình truy vấn thường gặp. Thực hiện phân trang có thể được viết dưới dạng một trợ giúp truy vấn:

javascript Copy
userSchema.query.paginate = function ({ page, limit }) {
    const skip = limit * (page - 1);
    return this.skip(skip).limit(limit);
};

Hooks

Hooks là các hàm được thực thi tại các thời điểm cụ thể trong vòng đời của tài liệu, cho phép bạn thêm hành vi tùy chỉnh. Chúng có thể áp dụng logic trước hoặc sau các thao tác lưu, cập nhật hay xóa tài liệu.

Ví dụ, bạn có thể gửi email kích hoạt tài khoản khi người dùng mới được tạo:

javascript Copy
userSchema.post("save", async function (doc, next) {
  // logic gửi email
  return next();
});

Kết Luận

Trên đây là những tính năng hữu ích của Mongoose Schemas mà bạn có thể áp dụng để viết mã nguồn gọn gàng và dễ bảo trì hơn. Hy vọng bài viết đã cung cấp cho bạn những kiến thức thiết thực trong việc phát triển ứng dụng với Mongoose.
source: viblo

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào