Mongoose là một thư viện JavaScript phổ biến, thường được sử dụng trong các ứng dụng Node.js để tương tác với cơ sở dữ liệu MongoDB. Bài viết này sẽ cung cấp cho bạn cái nhìn tổng quan về Mongoose và MongoDB, đồng thời khám phá những trường hợp mà các công nghệ này phù hợp nhất cho ứng dụng của bạn.
Mục Lục
MongoDB là gì?
MongoDB là một hệ quản trị cơ sở dữ liệu NoSQL, lưu trữ dữ liệu dưới dạng các tài liệu (document). Các tài liệu này thường có cấu trúc tương tự như JSON, ví dụ:
{ "firstName": "Jamie", "lastName": "Munro" }
Mỗi tài liệu được đặt trong một collection. Ví dụ, tài liệu trên định nghĩa một đối tượng người dùng (user), và đối tượng này thường là một phần của collection có tên là “users”.
Một trong những đặc điểm quan trọng của MongoDB là tính linh hoạt trong cấu trúc dữ liệu. Trong khi ví dụ trên cho thấy đối tượng người dùng có các thuộc tính firstName và lastName, thì những thuộc tính này không bắt buộc phải có trong mọi tài liệu của mỗi người dùng trong collection “users”. Điều này làm cho MongoDB khác biệt so với các cơ sở dữ liệu SQL như MySQL hoặc Microsoft SQL Server, vốn yêu cầu lược đồ (schema) được định nghĩa rõ ràng cho từng đối tượng mà nó lưu trữ.
Khả năng tạo các đối tượng động (dynamic object) được lưu trữ dưới dạng tài liệu trong cơ sở dữ liệu là lúc Mongoose trở nên hữu ích.
Mongoose là gì?
Mongoose là một Object Document Mapper (ODM). Điều này có nghĩa là Mongoose cho phép bạn định nghĩa các đối tượng với một lược đồ được định nghĩa rõ ràng, sau đó được ánh xạ tới một tài liệu MongoDB.
Mongoose cung cấp nhiều chức năng để tạo và làm việc với các lược đồ. Hiện tại, Mongoose có 8 kiểu dữ liệu (SchemaTypes) chính:
- String (Chuỗi)
- Number (Số)
- Date (Ngày)
- Buffer
- Boolean (Boolean)
- Mixed (Hỗn hợp)
- ObjectId
- Array (Mảng)
Mỗi kiểu dữ liệu cho phép bạn xác định:
- Giá trị mặc định (
default) - Hàm xác thực (
validate) - Trường bắt buộc (
required) - Hàm
getđể thao tác dữ liệu trước khi nó được trả về như một đối tượng - Hàm
setđể thao tác dữ liệu trước khi nó được lưu vào cơ sở dữ liệu - Tạo indexes để dữ liệu được nạp nhanh hơn
Ngoài các tùy chọn phổ biến này, một số kiểu dữ liệu nhất định cho phép bạn tùy chỉnh thêm cách dữ liệu được lưu trữ và truy xuất từ cơ sở dữ liệu. Ví dụ, kiểu dữ liệu String cũng cho phép bạn chỉ định các tùy chọn bổ sung sau:
- Chuyển đổi thành chữ thường (
lowercase) - Chuyển đổi thành chữ in hoa (
uppercase) - Cắt khoảng trắng thừa (
trim) - Một biểu thức chính quy (
match) có thể giới hạn dữ liệu được phép lưu trong quá trình xác thực - Một enum có thể định nghĩa một danh sách các chuỗi hợp lệ
Các thuộc tính Number và Date đều hỗ trợ chỉ định một giá trị tối thiểu (min) và tối đa (max) cho phép cho trường đó.
Bạn nên làm quen với hầu hết 8 kiểu dữ liệu. Tuy nhiên, có một số kiểu dữ liệu có thể ít gặp hơn, chẳng hạn như Buffer, Mixed, ObjectId và Array.
Kiểu dữ liệu Buffer cho phép bạn lưu trữ dữ liệu nhị phân. Một ví dụ phổ biến về dữ liệu nhị phân là hình ảnh hoặc tệp được mã hóa, chẳng hạn như tài liệu PDF.
Kiểu dữ liệu Mixed biến một thuộc tính thành một trường “thứ gì cũng được”. Trường này tương tự như cách nhà phát triển có thể sử dụng MongoDB vì nó không có cấu trúc xác định. Hãy cảnh giác với việc sử dụng kiểu dữ liệu này vì bạn sẽ mất nhiều tính năng tuyệt vời mà Mongoose cung cấp, chẳng hạn như xác thực dữ liệu và phát hiện các thay đổi của entity để tự động biết để cập nhật thuộc tính khi lưu.
Kiểu dữ liệu ObjectId thường chỉ định một liên kết đến một tài liệu khác trong cơ sở dữ liệu của bạn. Ví dụ: nếu bạn có một collection về sách (books) và tác giả (author), tài liệu sách có thể chứa thuộc tính ObjectId có tham chiếu đến một tác giả cụ thể của tài liệu.
Kiểu dữ liệu Array cho phép bạn lưu trữ các mảng giống như JavaScript. Với kiểu dữ liệu Array, bạn có thể thực hiện các chức năng phổ biến của JavaScript array, chẳng hạn như push, pop, shift, slice, v.v.
Tổng kết
MongoDB là một cơ sở dữ liệu cho phép bạn lưu trữ các tài liệu với cấu trúc động. Các tài liệu này được lưu bên trong một collection.
Mongoose là một thư viện JavaScript cho phép bạn định nghĩa các lược đồ với dữ liệu được định kiểu rõ ràng. Khi một lược đồ được định nghĩa, Mongoose cho phép bạn tạo một Model dựa trên một lược đồ cụ thể. Model của Mongoose sau đó được ánh xạ tới một tài liệu MongoDB thông qua định nghĩa lược đồ của Model.
Khi bạn đã xác định các lược đồ và model của mình, Mongoose chứa nhiều hàm khác nhau cho phép bạn xác thực tính hợp lệ, lưu, xóa và truy vấn dữ liệu của bạn bằng các hàm MongoDB phổ biến.
Cài đặt MongoDB
Để bắt đầu tạo các lược đồ và model của Mongoose, MongoDB phải được cài đặt và cấu hình. Bạn có thể truy cập trang MongoDB’s Download page để tải về phiên bản Community Server phù hợp với hệ điều hành của bạn. MongoDB cũng cung cấp Enterprise Server và hỗ trợ cài đặt trên đám mây.
Sau khi tải xuống và cài đặt MongoDB, bạn cần khởi động cơ sở dữ liệu. Tham khảo tài liệu của MongoDB về cách cài đặt MongoDB Community Edition để biết thêm chi tiết.
Thiết lập Mongoose
Mongoose là một framework JavaScript, và thường được sử dụng trong một ứng dụng Node.js. Nếu bạn đã cài đặt Node.js, bạn có thể chuyển sang bước tiếp theo. Nếu bạn chưa cài đặt Node.js, hãy truy cập trang Node.js Download page và chọn trình cài đặt cho hệ điều hành của bạn.
Với Node.js đã được thiết lập, hãy tạo một ứng dụng mới và cài đặt Mongoose NPM Package. Mở terminal và thực hiện các lệnh sau:
mkdir mongoose_basics
cd mongoose_basics
npm init -y
npm install mongoose
Bây giờ, hãy kết nối với một cơ sở dữ liệu MongoDB. Tạo một file index.js và thêm đoạn code sau:
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/mongoose_basics', function (err) {
if (err) throw err;
console.log('Successfully connected');
});
Dòng code đầu tiên yêu cầu thư viện mongoose. Tiếp theo, chúng ta mở một kết nối đến database mà chúng ta gọi là mongoose_basics bằng cách sử dụng hàm connect.
Hàm connect chấp nhận hai tham số tùy chọn khác. Tham số thứ hai là một đối tượng của các tùy chọn, ở đó bạn có thể định nghĩa username và password, nếu cần. Tham số thứ ba, cũng có thể là tham số thứ hai nếu bạn không có tùy chọn nào, là một hàm callback sau khi cố gắng kết nối. Hàm callback có thể được sử dụng theo một trong hai cách:
mongoose.connect(uri, options, function(error) {
// Kiểm tra lỗi trong kết nối ban đầu.
// Không có tham số thứ 2 cho callback.
});
// Hoặc sử dụng promises
mongoose.connect(uri, options)
.then(() => {
/** sẵn sàng sử dụng. Promise `mongoose.connect()` trả về undefined. */
})
.catch(err => {
/** xử lý lỗi kết nối ban đầu */
});
Để tránh phải giới thiệu về JavaScript Promises, chúng ta sẽ sử dụng cách đầu tiên.
Nếu có lỗi xảy ra khi kết nối với database, một exception sẽ được trả lại và tất cả các xử lý tiếp theo sẽ bị hoãn. Khi không có lỗi, một thông báo thành công sẽ được ghi lại vào console.
Mongoose bây giờ được thiết lập và kết nối với một cơ sở dữ liệu được gọi là mongoose_basics. Kết nối MongoDB của chúng ta không sử dụng username, password hoặc một port đặc biệt nào. Nếu bạn cần đặt các tùy chọn này hoặc bất kỳ tùy chọn nào khác trong khi kết nối, hãy xem lại Mongoose Documentation on connecting. Tài liệu này giải thích chi tiết về nhiều tùy chọn có sẵn cũng như cách tạo nhiều kết nối, connection pooling, replicas, v.v.
Định nghĩa lược đồ cho Mongoose
Trong phần giới thiệu, chúng ta đã thấy một đối tượng user có chứa hai thuộc tính: firstName và lastName. Chúng ta sẽ chuyển đổi document đó thành một lược đồ của Mongoose:
const userSchema = new mongoose.Schema({
firstName: String,
lastName: String
});
Đây là một lược đồ rất cơ bản chỉ chứa hai đặc tính mà không có thuộc tính nào liên kết với nó. Hãy mở rộng ví dụ này bằng cách chuyển đổi các thuộc tính tên và họ thành các đối tượng con của thuộc tính name. Thuộc tính name sẽ bao gồm cả tên và họ. Chúng ta cũng sẽ thêm một thuộc tính created theo kiểu Date.
const userSchema = new mongoose.Schema({
name: {
firstName: String,
lastName: String
},
created: Date
});
Như bạn có thể thấy, Mongoose cho phép bạn tạo các lược đồ rất linh hoạt với nhiều kết hợp khả dĩ khác nhau theo cách bạn có thể tổ chức dữ liệu của mình.
Trong ví dụ tiếp theo này, chúng ta sẽ tạo ra hai lược đồ mới để minh họa cách tạo mối quan hệ với một lược đồ khác: author và book. Lược đồ của book sẽ chứa một tham chiếu đến lược đồ của author.
const authorSchema = new mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: {
firstName: String,
lastName: String
},
biography: String,
twitter: String,
facebook: String,
linkedin: String,
profilePicture: Buffer,
created: { type: Date, default: Date.now }
});
Trên đây là lược đồ của author đã mở rộng dựa trên các khái niệm lược đồ của user mà chúng ta đã tạo trong ví dụ trước. Để liên kết Author và Book với nhau, thuộc tính đầu tiên của lược đồ của author là một thuộc tính _id, và đó là kiểu schema ObjectId. _id là cú pháp phổ biến để tạo khóa chính trong Mongoose và MongoDB. Sau đó, giống như lược đồ user, chúng ta đã định nghĩa một thuộc tính name có chứa tên và họ của tác giả.
Mở rộng theo lược đồ user, author chứa một số loại schema theo kiểu String. Chúng ta cũng đã thêm một loại schema Buffer có thể chứa ảnh hồ sơ của author. Thuộc tính cuối cùng là ngày tạo ra author; tuy nhiên, bạn có thể nhận thấy nó được tạo ra hơi khác vì nó đã có một giá trị mặc định đã được xác định “now”. Khi author được lưu vào database, thuộc tính này sẽ được đặt thành date/time hiện tại.
Để hoàn thành các ví dụ schema, hãy tạo một schema của book có một tham chiếu đến author bằng cách sử dụng kiểu schema ObjectId:
const bookSchema = new mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
title: String,
summary: String,
isbn: String,
thumbnail: Buffer,
author: { type: mongoose.Schema.Types.ObjectId, ref: 'Author' },
ratings: [{
summary: String,
detail: String,
numberOfStars: Number,
created: { type: Date, default: Date.now }
}],
created: { type: Date, default: Date.now }
});
Lược đồ book chứa một số thuộc tính của kiểu String. Như đã đề cập ở trên, nó chứa một tham chiếu đến lược đồ author. Để minh họa thêm các định nghĩa schema mạnh mẽ, schema book cũng chứa một Array các ratings. Mỗi xếp hạng bao gồm summary, detail, numberOfStars, và createddate (ngày tạo ra).
Mongoose cho phép bạn tạo ra các schema có tham chiếu đến các schema khác, hoặc như trong ví dụ trên với thuộc tính ratings, nó cho phép bạn tạo một Array các thuộc tính con có thể chứa trong một schema có liên quan (như book đến author) hoặc nội tuyến như trong ví dụ trên (với book cho một Array ratings).
Tạo và lưu các model của Mongoose
Khi các lược đồ của author và book chứng minh tính linh hoạt của Mongoose, chúng ta sẽ tiếp tục sử dụng các lược đồ đó và lấy ra một model Author và Book từ chúng.
const Author = mongoose.model('Author', authorSchema);
const Book = mongoose.model('Book', bookSchema);
Một Model của Mongoose, khi được lưu lại, tạo một Document trong MongoDB với các thuộc tính như đã được định nghĩa từ schema mà nó bắt nguồn.
Để minh hoạ cho việc tạo và lưu một object, trong ví dụ tiếp theo này, chúng ta sẽ tạo ra một số object: một Model Author và một số Model cho Book. Khi được tạo ra, các object này sẽ được lưu lại thành MongoDB bằng cách sử dụng phương thức save của Model.
const jamieAuthor = new Author({
_id: new mongoose.Types.ObjectId(),
name: { firstName: 'Jamie', lastName: 'Munro' },
biography: 'Jamie is the author of sentayho.com.vn MVC 5 with Bootstrap and sentayho.com.vn.',
twitter: 'https://twitter.com/endyourif',
facebook: 'https://www.facebook.com/End-Your-If-194251957252562/'
});
jamieAuthor.save(function(err) {
if (err) throw err;
console.log('Author successfully saved.');
const mvcBook = new Book({
_id: new mongoose.Types.ObjectId(),
title: 'sentayho.com.vn MVC 5 with Bootstrap and sentayho.com.vn',
author: jamieAuthor._id,
ratings:[{ summary: 'Great read' }]
});
mvcBook.save(function(err) {
if (err) throw err;
console.log('Book successfully saved.');
});
const knockoutBook = new Book({
_id: new mongoose.Types.ObjectId(),
title: 'Knockout.js: Building Dynamic Client-Side Web Applications',
author: jamieAuthor._id
});
knockoutBook.save(function(err) {
if (err) throw err;
console.log('Book successfully saved.');
});
});
Trong ví dụ trên, chúng ta đã vô tình dẫn một tham chiếu đến hai cuốn sách mới đây nhất của tôi. Ví dụ bắt đầu bằng cách tạo và lưu một jamieObject được tạo ra từ một model Author. Bên trong hàm save của jamieObject, nếu một lỗi xảy ra, ứng dụng sẽ xuất ra một exception. Khi việc lưu lại thành công, bên trong hàm save, hai đối tượng book được tạo ra và lưu lại. Tương tự như jamieObject, nếu một lỗi xảy ra khi đang lưu, một lỗi được xuất ra; nếu không, thông báo thành công sẽ được xuất ra trong bảng điều khiển.
Để tạo tham chiếu tới Author, đối tượng book chỉ ra cả tham chiếu đến khóa chính _id của schema author trong thuộc tính author của lược đồ book.
Xác thực dữ liệu trước khi lưu lại
Khá phổ biến với các dữ liệu mà sẽ tạo ra một model được nhập vào bởi một form trên một website. Vì lý do này, bạn nên xác nhận tính hợp lệ của dữ liệu này trước khi lưu Model vào MongoDB.
Trong ví dụ tiếp theo này, chúng ta sẽ cập nhật schema author trước đó để thêm xác nhận vào các thuộc tính sau: firstName, twitter, facebook và linkedin.
const authorSchema = new mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: {
firstName: { type: String, required: true },
lastName: String
},
biography: String,
twitter: {
type: String,
validate: {
validator: function(text) {
return text.indexOf('https://twitter.com/') === 0;
},
message: 'Twitter handle must start with https://twitter.com/'
}
},
facebook: {
type: String,
validate: {
validator: function(text) {
return text.indexOf('https://www.facebook.com/') === 0;
},
message: 'Facebook must start with https://www.facebook.com/'
}
},
linkedin: {
type: String,
validate: {
validator: function(text) {
return text.indexOf('https://www.linkedin.com/') === 0;
},
message: 'LinkedIn must start with https://www.linkedin.com/'
}
},
profilePicture: Buffer,
created: { type: Date, default: Date.now }
});
Thuộc tính firstName đã được gán cho thuộc tính required. Bây giờ khi chúng ta gọi hàm save, Mongoose sẽ trả về một lỗi với một thông báo cho biết thuộc tính firstName là bắt buộc. Chúng ta đã chọn không cho thuộc tính lastName thành required trong trường hợp Cher hoặc Madonna là author trong database của chúng ta.
Các thuộc tính twitter, facebook và linkedin đều có các trình xác thực tùy chỉnh rất giống nhau được áp dụng cho chúng. Họ đảm bảo rằng các giá trị bắt đầu với tên miền tương ứng của các mạng xã hội. Các field này không bắt buộc, vì vậy trình xác thực sẽ chỉ được áp dụng khi dữ liệu được cung cấp cho thuộc tính đó.
Tìm kiếm và cập nhật dữ liệu
Giới thiệu về Mongoose sẽ không hoàn chỉnh nếu không có ví dụ về tìm kiếm bản ghi và cập nhật một hoặc nhiều thuộc tính trên đối tượng đó.
Mongoose cung cấp một số chức năng khác nhau để tìm dữ liệu cho một Model cụ thể. Các hàm find, findOne và findById.
Hàm find và findOne đều chấp nhận một object làm đầu vào cho phép các tìm kiếm phức tạp, trong khi findById chỉ chấp nhận một giá trị duy nhất với hàm callback (sẽ có một ví dụ theo sau). Trong ví dụ tiếp theo này, chúng ta sẽ minh họa cách tìm tất cả các sách chứa string “mvc” trong tiêu đề.
Book.find({ title: /mvc/i }).exec(function(err, books) {
if (err) throw err;
console.log(books);
});
Bên trong hàm find, chúng ta đang tìm kiếm chuỗi “mvc” không phân biệt chữ hoa chữ thường trong thuộc tính title. Điều này được thực hiện bằng cách dùng cú pháp giống với việc tìm một string với JavaScript.
Việc gọi hàm find cũng được liên kết với các phương thức truy vấn khác, chẳng hạn như where, and, or, limit, sort, any, v.v.
Hãy mở rộng ví dụ trước nhằm giới hạn kết quả của chúng ta với năm book đầu tiên và sắp xếp theo ngày tạo (created date) giảm dần. Nó sẽ trả về tối đa năm book gần đây nhất có chứa “mvc” trong tựa đề.
Book.find({ title: /mvc/i })
.sort('-created')
.limit(5)
.exec(function(err, books) {
if (err) throw err;
console.log(books);
});
Sau khi áp dụng hàm find, thứ tự của các hàm khác không quan trọng vì tất cả các hàm có kết nối được biên dịch cùng nhau thành một truy vấn duy nhất và không được thực hiện cho đến khi hàm exec được gọi.
Như đã đề cập trước đó, hàm findById được thực hiện hơi khác một chút. Hàm này thực hiện ngay lập tức và chấp nhận một hàm callback, thay vì cho phép một chuỗi kết nối các hàm. Trong ví dụ tiếp theo, chúng ta đang truy vấn một author cụ thể bằng _id của họ.
Author.findById('59b31406beefa1082819e72f', function(err, author) {
if (err) throw err;
console.log(author);
});
_id trong trường hợp của bạn có thể hơi khác. Chúng ta đã sao chép _id này từ một console.log trước đó khi tìm danh sách các book có “mvc” trong tựa đề.
Khi một object đã được trả về, bạn có thể sửa đổi bất kỳ thuộc tính nào của object đó để cập nhật. Khi bạn đã thực hiện các thay đổi cần thiết, bạn gọi phương thức save, giống như khi bạn đang tạo object. Trong ví dụ tiếp theo, chúng ta sẽ mở rộng ví dụ findbyId và cập nhật thuộc tính linkedin của author.
Author.findById('59b31406beefa1082819e72f', function(err, author) {
if (err) throw err;
author.linkedin = 'https://www.linkedin.com/in/jamie-munro-8064ba1a/';
author.save(function(err) {
if (err) throw err;
console.log('Author updated successfully');
});
});
Sau khi một author được truy xuất thành công, thuộc tính linkedin được thiết lập và hàm save được gọi. Mongoose có thể phát hiện rằng thuộc tính linkedin đã được thay đổi và nó sẽ gửi một thông báo cập nhật tới MongoDB chỉ cho các thuộc tính đã được sửa đổi. Nếu xảy ra lỗi khi lưu, một exception sẽ được gửi đi và sẽ tạm dừng ứng dụng. Khi thành công, một thông báo thành công được ghi vào console.
Mongoose cũng cung cấp hai hàm bổ sung để tìm kiếm một đối tượng và lưu lại cùng lúc với các hàm được đặt tên khá phù hợp: findByIdAndUpdate và findOneAndUpdate. Hãy nâng cấp ví dụ trước để sử dụng findByIdAndUpdate.
Author.findByIdAndUpdate('59b31406beefa1082819e72f',
{ linkedin: 'https://www.linkedin.com/in/jamie-munro-8064ba1a/' },
function(err, author) {
if (err) throw err;
console.log(author);
});
Trong ví dụ trước, các thuộc tính để cập nhật được cung cấp dưới dạng một đối tượng cho tham số thứ hai của hàm findByIdAndUpdate. Hàm callback bây giờ là tham số thứ ba. Khi cập nhật thành công, object author được trả về có chứa thông tin đã được cập nhật. Điều này được ghi vào console để xem các thuộc tính đã được cập nhật của tác giả.
Ví dụ code đầy đủ
Trong suốt bài viết này, chúng ta đã cung cấp các trích đoạn code nhỏ xác định một hành động rất cụ thể, chẳng hạn như tạo schema, tạo model, v.v. Hãy kết hợp chúng lại với nhau trong một ví dụ đầy đủ.
Đầu tiên, chúng ta sẽ tạo hai file bổ sung: author.js và book.js. Các tệp này chứa các định nghĩa schema tương ứng của chúng và việc tạo ra model. Dòng mã cuối cùng giúp cho model sẵn sàng để sử dụng trong file index.js.
Hãy bắt đầu với file author.js:
const mongoose = require('mongoose');
const authorSchema = new mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: {
firstName: { type: String, required: true },
lastName: String
},
biography: String,
twitter: {
type: String,
validate: {
validator: function(text) {
return text.indexOf('https://twitter.com/') === 0;
},
message: 'Twitter handle must start with https://twitter.com/'
}
},
facebook: {
type: String,
validate: {
validator: function(text) {
return text.indexOf('https://www.facebook.com/') === 0;
},
message: 'Facebook must start with https://www.facebook.com/'
}
},
linkedin: {
type: String,
validate: {
validator: function(text) {
return text.indexOf('https://www.linkedin.com/') === 0;
},
message: 'LinkedIn must start with https://www.linkedin.com/'
}
},
profilePicture: Buffer,
created: { type: Date, default: Date.now }
});
const Author = mongoose.model('Author', authorSchema);
module.exports = Author;
Tiếp theo là file book.js:
const mongoose = require('mongoose');
const bookSchema = new mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
title: String,
summary: String,
isbn: String,
thumbnail: Buffer,
author: { type: mongoose.Schema.Types.ObjectId, ref: 'Author' },
ratings: [{
summary: String,
detail: String,
numberOfStars: Number,
created: { type: Date, default: Date.now }
}],
created: { type: Date, default: Date.now }
});
const Book = mongoose.model('Book', bookSchema);
module.exports = Book;
Và cuối cùng, file index.js được cập nhật:
const mongoose = require('mongoose');
const Author = require('./author');
const Book = require('./book');
mongoose.connect('mongodb://localhost/mongoose_basics', function (err) {
if (err) throw err;
console.log('Successfully connected');
const jamieAuthor = new Author({
_id: new mongoose.Types.ObjectId(),
name: { firstName: 'Jamie', lastName: 'Munro' },
biography: 'Jamie is the author of sentayho.com.vn MVC 5 with Bootstrap and sentayho.com.vn.',
twitter: 'https://twitter.com/endyourif',
facebook: 'https://www.facebook.com/End-Your-If-194251957252562/'
});
jamieAuthor.save(function(err) {
if (err) throw err;
console.log('Author successfully saved.');
const mvcBook = new Book({
_id: new mongoose.Types.ObjectId(),
title: 'sentayho.com.vn MVC 5 with Bootstrap and sentayho.com.vn',
author: jamieAuthor._id,
ratings:[{ summary: 'Great read' }]
});
mvcBook.save(function(err) {
if (err) throw err;
console.log('Book successfully saved.');
});
const knockoutBook = new Book({
_id: new mongoose.Types.ObjectId(),
title: 'Knockout.js: Building Dynamic Client-Side Web Applications',
author: jamieAuthor._id
});
knockoutBook.save(function(err) {
if (err) throw err;
console.log('Book successfully saved.');
});
});
});
Trong ví dụ trên, tất cả các hoạt động của Mongoose được chứa trong hàm connect. Các file author và book được bao kèm với hàm require sau khi liên kết với thư viện mongoose.
Với MongoDB đang chạy, bây giờ bạn có thể hoàn thành ứng dụng Node.js đầy đủ bằng lệnh sau đây:
node index.js
Sau khi chúng ta lưu một số data vào database của mình, chúng ta sẽ cập nhật file index.js với các hàm find như sau:
const mongoose = require('mongoose');
const Author = require('./author');
const Book = require('./book');
mongoose.connect('mongodb://localhost/mongoose_basics', function (err) {
if (err) throw err;
console.log('Successfully connected');
Book.find({ title: /mvc/i })
.sort('-created')
.limit(5)
.exec(function(err, books) {
if (err) throw err;
console.log(books);
});
Author.findById('59b31406beefa1082819e72f', function(err, author) {
if (err) throw err;
author.linkedin = 'https://www.linkedin.com/in/jamie-munro-8064ba1a/';
author.save(function(err) {
if (err) throw err;
console.log('Author updated successfully');
});
});
Author.findByIdAndUpdate('59b31406beefa1082819e72f',
{ linkedin: 'https://www.linkedin.com/in/jamie-munro-8064ba1a/' },
function(err, author) {
if (err) throw err;
console.log(author);
});
});
Một lần nữa, bạn có thể chạy ứng dụng bằng lệnh: node index.js.
Kết luận
Sau khi đọc bài viết này, bạn có thể tạo các Model và Schema cực kỳ linh hoạt cho Mongose, áp dụng xác thực đơn giản hoặc phức tạp, tạo và cập nhật tài liệu và cuối cùng tìm kiếm các tài liệu đã được tạo.
Hy vọng bây giờ bạn cảm thấy thoải mái khi sử dụng Mongoose. Nếu bạn đang tìm hiểu thêm, hãy xem các Mongoose Guides, các hướng dẫn này nghiên cứu sâu hơn các chủ đề nâng cao như population, middleware, promises, v.v.
