Đàm đạo về ORM và Query Builder - Sequelize vs Knex!!!

Đàm đạo về ORM và Query Builder - Sequelize vs Knex!!!

Tin ngắn hàng ngày dành cho bạn
  • altcha-org/altcha là một dự án mã nguồn mở thay thế giải pháp reCaptcha hay hCaptcha.

    Nghiên cứu mấy dự án này cũng hay ho phết, vì coi như tìm hiểu luôn cách nó hoạt động và ngăn chặn hành vi "spam" ra sao 🤓

    » Xem thêm
  • Manus đã chính thức mở cửa cho tất cả người dùng rồi đấy mọi người. Cho những ai chưa biết thì đây là một công cụ viết báo cáo (làm mưa làm gió) giống như Deep Research của OpenAI á. Mỗi ngày được miễn phí 300 Credits để nghiên cứu. Mỗi lượt nghiên cứu tiêu tốn tuỳ thuộc vào độ phức tạp của yêu cầu. À với cả họ đang có chương trình tặng miễn phí Credits hay sao á. Như mình thì vào thấy được hẳn 2000.

    Mình dùng thử, so sánh với cùng một lệnh giống như đợt trước dùng bên Deep Research thì nội dung khác biệt nhau hoàn toàn. Manus báo cáo như kiểu viết văn hơn so với OpenAI là các gạch đầu dòng và bảng biểu.

    À lúc đăng ký xong có bắt nhập số điện thoại để xác minh, nếu lỗi thì các bạn đợi qua ngày thử lại xem có được không nhé.

    » Xem thêm
  • Mọi người chắc nghe nhiều về xu hướng tìm kiếm thông tin bằng AI chứ không cần công cụ tìm kiếm như Google nữa rồi đúng không? Không đâu xa ánh xạ vào bản thân thì thấy đúng thật, thi thoảng mới tìm kiếm thôi chứ còn đâu toàn hỏi tụi AI.

    Ngay từ đầu viết blog, thứ mà mình hướng đến là chia sẻ kinh nghiệm chứ không phải là những bài mang nặng tính kỹ thuật, máy móc, hướng dẫn từ đầu... Vì thời điểm đó đã có quá nhiều người làm nội dung này rồi và họ làm rất tốt, tại sao mình phải cố phát minh lại bánh xe? Một điều nữa là tin tưởng độc giả của mình có khả năng tìm hiểu vấn đề. Nếu bạn đọc đủ nhiều các bài viết trên blog thì thấy mình luôn cố gắng chèn thêm các liên kết tham khảo ngoài bài viết, nêu ra vấn đề mở và rất ít khi kết luận chắc chắn một điều gì đó.

    Mình đã cố gắng rèn luyện kỹ năng viết, kỹ năng trình bày và cả cách tương tác với độc giả để mang lại giá trị cho họ. Nhiều lúc ngồi lật lại các con số thống kê thấy lượng đọc bài viết tăng lên lại cảm thấy vui. Nhưng khi nguồn truy cập đến từ Google thì lại thấy buồn, vì điều đó chứng tỏ họ biết đến mình chỉ khi đang cố đi tìm giải pháp, có thể họ chỉ đọc chớp nhoáng, may ra tìm được cách giải quyết và thế là đóng cửa sổ trình duyệt rồi đi như một cơn gió.

    Chừng vài tháng đổ lại đây, một điều khiến mình rất vui đó là lượng người truy cập thẳng vào trang chủ mà không thông qua công cụ tìm kiếm đang tăng dần lên, có nhiều hôm lượng truy cập tự nhiên còn cao hơn cả đến từ Google. Điều đó chứng tỏ độc giả đã có thói quen quay lại trang của mình nhiều hơn và họ tìm thấy được giá trị từ blog mang lại. Vui mừng khôn xiết 🤩

    Bên cạnh đó thì lượng truy cập vào chuyên mục Threads - tức là mục mình đang viết bài này đang cao hơn bao giờ hết. Điều đó chứng tỏ xu hướng đi theo tin nhanh là đúng đắn. Mình có thể ngồi cả ngày để viết tin ngắn cho bạn đọc vì nó rất nhanh mà tiện, không tốn công đi tìm tài liệu để viết, không tốn cả thời gian viết nữa, còn mình thì có rất nhiều thứ để chia sẻ 😅. Nhưng không vì thế mà bỏ bê các bài viết dài, vì dài thì có nhiều thông tin để chia sẻ hơn.

    Vài lời tâm sự thế thôi chứ hơn một tháng nay mình chưa viết bài viết mới nào vì công việc bận quá. Xong lâu dần cứ trì hoãn lại thành lười. À với cả tháng 5 này rất thích hợp để đọc các cuốn sách về cách mạng á. Có hôm đọc đến 2 giờ sáng mới đi ngủ 🥱

    » Xem thêm

Vấn đề

Trong dự án bất kể chúng ta sử dụng loại cơ sở dữ liệu nào thì việc lựa chọn một thư viện (client) hỗ trợ kết nối và truy vấn dữ liệu là một điều hết sức cần thiết.

Có 3 phương pháp phổ biến mà các thư viện hỗ trợ truy vấn dữ liệu đó là Raw Query, Query Builder và ORM. Mỗi phương pháp có cách thức triển khai khác nhau và ưu/nhược điểm khác nhau, tuỳ vào yêu cầu của dự án mà chúng ta sẽ lựa chọn để tận dụng tối đa sức mạnh của chúng.

Bài viết ngày hôm nay tôi sẽ trình bày và phân tích ra những ưu - nhược điểm cũng như nên sử dụng phương pháp nào trong dự án tiếp theo của bạn.

Raw, Builder và ORM

Query Raw đúng như cái tên của nó, bạn sẽ trực tiếp viết lệnh SQL vào trong mã của dự án, nghĩa là bạn truy vấn dữ liệu SQL như thế nào thì trong mã của bạn viết như thế.

Ví dụ trong MySQL, có một thư viện giúp bạn truy vấn dữ liệu bằng các câu raw đó là mysql2. Thư viện này cũng được nhiều thư viện khác sử dụng làm Dependencies.

Nếu sử dụng mysql2 cú pháp truy vấn dữ liệu sẽ là:

const mysql = require('mysql2');

const connection = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  database: 'test'
});

connection.query('SELECT * FROM `person` WHERE `name` = "Page" AND `age` > 45');

Có thể thấy raw query trực tiếp viết lệnh SQL trong mã, điều này tăng tốc độ cho truy vấn vì bạn có thể dễ dàng viết những lệnh tối ưu nhất, không phải qua bộ chuyển đổi nào nữa, đồng thời dễ đàng viết những câu truy vấn dài và phức tạp. Tuy nhiên nếu dùng cách này bạn phải xác định được ngay từ đầu phải chọn cơ sở dữ liệu nào bởi việc đó ảnh hưởng đến việc lựa chọn thư viện. Không phải thư viện nào cũng kết nối được với MySQL hay Postgres... Ví dụ trên thư viện mysql2 chỉ sử dụng được cho MySQL, nếu dùng Postgres hay SQLServer bạn sẽ phải tìm thư viện khác. Hơn nữa những câu query raw có thể sẽ không hoạt động khi bạn chuyển dự án sang sử dụng một cơ sở dữ liệu khác.

Query builder được cải tiến hơn về cú pháp, nó có thể là một thư viện hỗ trợ nhiều loại cơ sở dữ liệu khác như MySQL, Postgres, SQLServer... Nghĩa là một thư viện bạn có thể dễ dàng kết nối đến nhiều loại cơ sở dữ liệu khác nhau.

Query builder có một tổ hợp cú pháp truy vấn, bạn sẽ ráp chúng lại với nhau để lấy ra dữ liệu mà mình mong muốn. Cũng chính vì thế mà nó được gọi là builder.

Ví dụ có một thư viện hỗ trợ Query builder phổ biến là Knex.

const knex = require('knex')({
  client: 'mysql',
  connection: {
      host: 'localhost',
      user: 'root',
      database: 'test'
  }
});

knex
    .select('*')
    .where("name", "Page")
    .where("age", ">", 45)
    .from("person");

Thay vì viết các lệnh raw, Query builder cung cấp các hàm chaining (chaining function) để hỗ trợ truy vấn. Điều đó giúp cho nó linh hoạt chuyển đổi sang lệnh SQL tương thích với từng loại cơ sở dữ liệu. Bạn cũng có thể dễ dàng xem lệnh raw bằng cách gọi hàm .toString().

knex
    .select('*')
    .where("name", "Page")
    .where("age", ">", 45)
    .from("table")
    .toString();

// SELECT * FROM `person` WHERE `name` = "Page" AND `age` > 45;

Query builder giúp mã của bạn trông gọn gàng và có cấu trúc hơn. Cú pháp đồng nhất, hỗ trợ nhiều loại cơ sở dữ liệu. Phù hợp cho dự án sử dụng nhiều truy vấn phức tạp mà vẫn muốn cú pháp rõ ràng.

ORM (Object Relational Mapping) cung cấp giải pháp ánh xạ cơ sở dữ liệu vào mã. Nó trừu tượng hoá các bảng thành các đối tượng (Class) trong mã.

Vì trừu tượng nên thuận tiện cho truy vấn và lấy dữ liệu, các thao tác trực tiếp với cơ sở dữ liệu được che giấu để giảm tải đi sự phức tạp của mã. Sequelize là một thư viện phổ biến hỗ trợ ORM. Cũng như Query builder, sequelize hỗ trợ cùng lúc nhiều loại cơ sở dữ liệu khác nhau.

ORM ban đầu sẽ phải viết nhiều mã hơn để khai báo lớp (Class) tương ứng với bảng (tables) trong cơ sở dữ liệu. Ví dụ đây là khai báo của bảng person:

const User = sequelize.define('person', {
  name: {
    type: DataTypes.STRING,
    allowNull: false,
  },
  age: {
    type: DataTypes.STRING,
    allowNull: false,
  }
}

Sau đó để truy vấn rất đơn giản:

const users = await User.findAll({
    where: {
        "name": "Page",
        "age": {
            [Op.gt]: 45
        },
});

Một lợi ích của ORM đó là các users trong kết quả truy vấn ở trên được ánh xạ trực tiếp với các dòng trong cơ sở dữ liệu, qua đó chúng ta có thể thao tác sửa, xoá dữ liệu trực tiếp từ chúng. Ví dụ sau sẽ cập nhật tên của dòng đầu tiên của kết quả tìm kiếm thành Page Updated:

users[0].setAttribute("name", "Page Updated");
await users[0].save();

Bởi vì ORM đã ánh xạ từng dòng dữ liệu vào các đối tượng tương ứng thế nên việc bạn thao tác với các đối tượng cũng giống như đang thao tác với cơ sở dữ liệu mà không cần dùng đến bất kì mã SQL nào.

Ngoài ra ORM còn hỗ trợ migrate (thêm, sửa, xoá) các bảng và dữ liệu thông qua Class, bạn có thể tìm hiểu thêm ở trang chủ của Sequelize.

Tuy tiện ích là thế nhưng đổi lại đó là hiệu năng của những câu truy vấn không thực sự tốt, bởi vì Sequelize che giấu sự phức tạp của cách lệnh truy vấn và phải dùng những lệnh theo "đường vòng" để hỗ trợ nhiều loại cơ sở dữ liệu khác nhau.

Ngoài ra nếu dự án có nhiều truy vấn nâng cao & phức tạp thì sequelize không phải là một sự lựa chọn tối ưu. Thay vào đó bạn hãy sử dụng Raw query hoặc Query builder.

Tổng kết

Trên đây là 3 phương pháp sử dụng Database client để sử dụng cơ sở dữ liệu. Tuỳ theo dự án mà chúng ta sẽ lựa chọn phương pháp phù hợp nhất. Raw query vẫn cho hiệu năng tối ưu nhất tuy nhiên phải viết nhiều mã. ORM dễ dàng truy vấn hơn nhưng lại khó sử dụng trong những trường hợp truy vấn phức tạp. Query builder cân bằng giữa hai cách tuy nhiên hãy xem xét kĩ trước khi sử dụng.

Cao cấp
Hello

5 bài học sâu sắc

Mỗi sản phẩm đi kèm với những câu chuyện. Thành công của người khác là nguồn cảm hứng cho nhiều người theo sau. 5 bài học rút ra được đã thay đổi con người tôi mãi mãi. Còn bạn? Hãy bấm vào ngay!

Mỗi sản phẩm đi kèm với những câu chuyện. Thành công của người khác là nguồn cảm hứng cho nhiều người theo sau. 5 bài học rút ra được đã thay đổi con người tôi mãi mãi. Còn bạn? Hãy bấm vào ngay!

Xem tất cả

Đăng ký nhận thông báo bài viết mới

hoặc
* Bản tin tổng hợp được gửi mỗi 1-2 tuần, huỷ bất cứ lúc nào.

Bình luận (2)

Nội dung bình luận...
Avatar
Thành Đỗ2 năm trước

Orm vẫn tiện nhất

Trả lời
Avatar
Hương Trịnh2 năm trước

@gif [UEN9mQU3qPOL7IVWvp] Haha h còn cả cmt = gif à xịn thế

Trả lời