Cũng tương tự như các framework backend khác, thì NodeJS cũng cung cấp cho chúng ta đầy đủ các hàm cho các tính năng Create (tạo), Read (đọc), Update (cập nhật), Delete (xoá) và nó cũng tương đối đơn giản vì tận dụng được sẵn các tính năng của javascript.

Thêm dữ liệu

Chúng ta có hai hàm để thêm dữ liệu:

  1. Hàm insertOne: Thêm một bản ghi vào cơ sở dữ liệu.
  2. Hàm insertMany: Thêm nhiều bản ghi vào cơ sở dữ liệu.
    Giả sử chúng ta cần thêm một danh sách những người dùng vào cơ sở dữ liệu, chúng ta có thể làm như sau:
const { MongoClient } = require('mongodb');

const url = 'mongodb://root:123456@localhost:27017/test';
const dbName = 'test';

const randomString = (length) => {
  const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  let result = '';
  for (let i = 0; i < length; i++) {
    result += characters.charAt(Math.floor(Math.random() * characters.length));
  }
  return result;
};

const generateUsers = (numUsers) => {
  const users = [];
  for (let i = 0; i < numUsers; i++) {
    const randomNum = Math.floor(Math.random() * 10000);
    const username = `user${randomNum}`;
    const email = `user${randomNum}@example.com`;
    const password = randomString(8);
    const displayName = `User ${randomNum}`;

    users.push({
      username,
      email,
      password,
      displayName,
    });
  }
  return users;
};

async function main() {
  const client = new MongoClient(url);

  try {
    await client.connect();
    console.log('Connected successfully to MongoDB');

    const db = client.db(dbName);
    const collection = db.collection('users');

    const user = generateUsers(1)[0];
    const users = generateUsers(1000);

    const insertOneResult = await collection.insertOne(user);
    console.log(`${insertOneResult} users inserted successfully!`);

    const insertManyResult = await collection.insertMany(users);
    console.log(`${insertManyResult.insertedCount} users inserted successfully!`);
    
  } catch (err) {
    console.error('Error connecting or inserting:', err);
  } finally {
    await client.close();
  }
}

main().catch(console.error);

Ở đây chúng ta tạo ngẫu nhiên 1 và 1000 người dùng, sau đó sử dụng hàm insertOne để thêm 1 người dùng và hàm insertMany để thêm nhiều người dùng. Chạy chương trình chúng ta sẽ có kết quả:

Connected successfully to MongoDB
[object Object] users inserted successfully!
1000 users inserted successfully!

Cập nhật dữ liệu

Chúng ta có thể cập nhật dữ liệu thông qua 2 hàm:

  1. updateOne: Cập nhật một bản ghi.
  2. updateMany: Cập nhật nhiều bản ghi.
    Ví dụ:
const updateOneResult = await collection.updateOne(
  { username: user.username },
  { $set: { password: 'newpassword123' } }
);
console.log(`${updateOneResult.modifiedCount} user updated successfully!`);

const updateManyResult = await collection.updateMany(
  { username: { $regex: '^user' } },
  { $set: { displayName: 'Updated User' } }
);

Ở đây chúng ta:

  1. Cập nhật một người dùng có username thoả mãn điều kiều và cài đặt mật khẩu mới là newpassword123.
  2. Cập nhật tất cả người dùng có tên đăng nhập thoả mãn điều kiện và cài đặt tên hiển thị là: Updated User.
    Chạy chương trình và chúng ta sẽ thấy có thêm log in ra kiểu thế này:
1 user updated successfully!
4005 users updated successfully!

Truy vấn dữ liệu

Chúng ta có thể truy vấn dữ liệu thông qua 2 hàm:

  1. findOne: Truy vấn để lấy ra một bản ghi thoả mãn điều kiện.
  2. find: Truy vấn để lấy ra một danh sách các bản ghi thoả mãn điều kiện.
    Ví dụ:
const singleUser = await collection.findOne({ username: user.username });
console.log('Single user found:', singleUser);

const userList = await collection.find({ username: { $regex: '^user' } }).limit(5).toArray();
console.log('List of users found:', userList);

Ở đây chúng ta:

  1. Lấy ra một người dùng với tên đăng nhập thoả mãn điều kiện.
  2. Lấy ra một danh sách 5 người dùng với tên đăng nhập thoả mãn điều kiện.
    Chạy chương trình, chúng ta sẽ nhận được log kiểu như sau:
Single user found: {
  _id: new ObjectId('6717225ec226b434312ccbde'),
  username: 'user6418',
  email: 'user6418@example.com',
  password: 'newpassword123',
  displayName: 'Updated User'
}
List of users found: [
  {
    _id: new ObjectId('67162d34bec26a295aa81619'),
    username: 'user5345',
    email: 'user5345@example.com',
    password: 'eHu9Ktfs',
    displayName: 'Updated User'
  },
  {
    _id: new ObjectId('67162d3e9c07ce837f3eef61'),
    username: 'user9028',
    email: 'user9028@example.com',
    password: 'XUEQUFCp',
    displayName: 'Updated User'
  },
  {
    _id: new ObjectId('67162d3e9c07ce837f3eef62'),
    username: 'user2037',
    email: 'user2037@example.com',
    password: 'ex2DELxW',
    displayName: 'Updated User'
  },
  {
    _id: new ObjectId('67162d3e9c07ce837f3eef63'),
    username: 'user7903',
    email: 'user7903@example.com',
    password: 'e7xnKUhZ',
    displayName: 'Updated User'
  },
  {
    _id: new ObjectId('67162d3e9c07ce837f3eef64'),
    username: 'user6511',
    email: 'user6511@example.com',
    password: 'pFP0TNtz',
    displayName: 'Updated User'
  }
]

Chúng ta cũng có thể đếm các bản ghi thông qua hàm countDocuments như sau:

const totalUsers = await collection.countDocuments();
console.log(`Total users: ${totalUsers}`);

const usersByCondition = await collection.countDocuments({ username: { $regex: '^user1' } });
console.log(`Users whose username starts with 'user1': ${usersByCondition}`);

Chạy chương trình và kết quả chúng ta nhận được là:

Total users: 6007
Users whose username starts with 'user1': 676

Xoá dữ liệu

Chúng ta có thể xoá dữ liệu thông qua hai hàm:

  1. deleteOne: Xoá một bản ghi thoả mãn điều kiện.
  2. deleteMany: Xoá nhiều bản ghi thoả mãn điều kiện.
    Ví dụ:
const deleteOneResult = await collection.deleteOne({ username: { $regex: '^user' } });
console.log(`${deleteOneResult.deletedCount} user deleted successfully!`);

const deleteManyResult = await collection.deleteMany({ username: { $regex: '^user9' } });
console.log(`${deleteManyResult.deletedCount} users deleted successfully!`);

Ở đây chúng ta:

  1. Xoá một bản ghi có tên đăng nhập thoả mãn điều kiện.
  2. Xoá nhiều bản ghi có tên đăng nhập thoả mãn điều kiện.
    Chạy chương trình chúng ta sẽ nhận được thêm log kiểu thế này:
1 user deleted successfully!
820 users deleted successfully!

Chú ý: Việc xoá bản ghi sẽ làm phát sinh ra rất nhiều log, điều này có thể dẫn đến ổ cứng bị đầy rất nhanh, vậy nên không nên lạm dụng phương thức xoá dữ liệu. Ngày nay dữ liệu thường sẽ được cập nhật trạng thái hơn là xoá vĩnh viễn.

Tăng giá trị của một trường trong 1 bản ghi

Giả sử chúng ta không thích sử dụng _id kiểu ObjectId, chúng ta có thể sử kiểu số nguyên, lúc này chúng ta có thể tạo ra một collection có tên counters, chúng ta sẽ không cần khởi toạ schema nhưng cơ bản thì schema này sẽ như sau:

{"_id": string,"maxId": number}

Hoặc đơn giản là chúng ta sử dụng mã nguồn NodeJS như sau:

const countersCollection = db.collection('counters');

const result = await countersCollection.findOneAndUpdate(
  { _id: 'users' },
  { $inc: { maxId: 1 } },
  { returnDocument: 'after', upsert: true }
);
console.log('newId: ', result.maxId);

Ở đây chúng ta đang sử dụng hàm findOneAndUpdate và toán tử $inc. Toán tử này sẽ làm tăng giá trị của maxId lên một đơn vị và chúng ta có thể lấy kết quả result.maxId để làm id cho bản ghi mới.

Tổng kết

Như vậy chúng ta đã cùng nhau tìm hiểu CRUD MongoDB với NodeJS, trong bài tiếp theo chúng ta sẽ tìm hiểu về truy vấn phân trang nhé.


Cám ơn bạn đã quan tâm đến bài viết|video này. Để nhận được thêm các kiến thức bổ ích bạn có thể:

  1. Đọc các bài viết của TechMaster trên facebook: https://www.facebook.com/techmastervn
  2. Xem các video của TechMaster qua Youtube: https://www.youtube.com/@TechMasterVietnam nếu bạn thấy video/bài viết hay bạn có thể theo dõi kênh của TechMaster để nhận được thông báo về các video mới nhất nhé.
  3. Chat với techmaster qua Discord: https://discord.gg/yQjRTFXb7a