Sunday, January 19, 2025

Hệ quản trị cơ sở dữ liệu MongoDB

-

1. Tổng quan.

MongoDB là một hệ quản trị cơ sở dữ liệu (DBMS) thuộc loại NoSQL, được thiết kế để lưu trữ và truy xuất dữ liệu một cách linh hoạt và mở rộng.

  • Kiến Trúc NoSQL:
    • MongoDB thuộc loại cơ sở dữ liệu NoSQL, có nghĩa là nó không sử dụng mô hình dữ liệu quan hệ như SQL databases. Thay vào đó, nó sử dụng cấu trúc JSON-like có tên là BSON (Binary JSON) để lưu trữ dữ liệu.
  • Dữ Liệu Hướng Tài Liệu:
    • MongoDB lưu trữ dữ liệu trong các tài liệu (documents), mà mỗi tài liệu là một bản ghi dữ liệu đơn. Các tài liệu được tổ chức trong các bộ sưu tập (collections), giống như các bảng trong cơ sở dữ liệu quan hệ.
  • Khả Năng Mở Rộng:
    • MongoDB được thiết kế để mở rộng dễ dàng và linh hoạt, cho phép mở rộng theo cả chiều rộng ngang (horizontal scaling) và chiều rộng dọc (vertical scaling). Điều này giúp MongoDB phù hợp với các ứng dụng có yêu cầu lớn về dữ liệu và khả năng mở rộng.
  • Lập Trình Bằng Nhiều Ngôn Ngữ:
    • MongoDB hỗ trợ nhiều ngôn ngữ lập trình như JavaScript, Python, Java, C#, và nhiều ngôn ngữ khác. Điều này giúp những nhà phát triển có thể sử dụng ngôn ngữ ưa thích của họ để tương tác với cơ sở dữ liệu.
  • Indexing và Truy Vấn Hiệu Quả:
    • MongoDB hỗ trợ các kỹ thuật indexing để tối ưu hóa tìm kiếm và truy vấn dữ liệu. Nó cũng cung cấp một ngôn ngữ truy vấn linh hoạt, có thể thao tác với dữ liệu bằng cách sử dụng các toán tử và phương thức đặc biệt.
  • Dữ Liệu Phân Tán và Tích Hợp Cloud:
    • MongoDB hỗ trợ dữ liệu phân tán và có khả năng tích hợp với các dịch vụ đám mây như AWS, Azure, và Google Cloud. Điều này giúp người dùng triển khai và quản lý cơ sở dữ liệu của họ một cách thuận tiện.
  • Community và Ecosystem Mạnh Mẽ:
    • MongoDB có một cộng đồng sử dụng và đóng góp lớn, cùng với một hệ sinh thái (ecosystem) phong phú của các công cụ và thư viện hỗ trợ như Mongoose (trong Node.js) và PyMongo (trong Python).
  • An Toàn và Bảo Mật:
    • MongoDB cung cấp các tính năng an toàn và bảo mật như xác thực, quản lý quyền, mã hóa dữ liệu, và các công cụ giám sát để đảm bảo an ninh của cơ sở dữ liệu.

2. Cài đặt MongoDB.

Tôi sẽ cài đặt MongoDB chung với Server chạy Prometheus luôn nhé. Để cài đặt MongoDB trên Ubuntu, bạn có thể làm theo các bước sau:

Cập nhật các gói phần mềm.

sudo apt update

Cài đặt gói MongoDB.

sudo apt install mongodb -y

Sau khi quá trình cài đặt hoàn tất, MongoDB sẽ được khởi động mặc định. Bạn có thể kiểm tra trạng thái của dịch vụ MongoDB bằng lệnh.

sudo systemctl status mongodb

Nếu dịch vụ đang chạy, bạn sẽ thấy thông báo “active (running)”.

● mongodb.service - An object/document-oriented database
   Loaded: loaded (/lib/systemd/system/mongodb.service; enabled; vendor preset: enabled)
   Active: active (running) since Tue 2023-06-20 03:07:02 UTC; 7s ago
     Docs: man:mongod(1)
 Main PID: 2970 (mongod)
    Tasks: 23 (limit: 4915)
   CGroup: /system.slice/mongodb.service
           └─2970 /usr/bin/mongod --unixSocketPrefix=/run/mongodb --config /etc/mongodb.conf

Jun 20 03:07:02 ubuntu1804 systemd[1]: Started An object/document-oriented database.

Kiểm tra cài đặt.

Sau khi cài đặt xong, hãy mở cửa sổ dòng lệnh (command line) và thử gõ mongo --version. Nếu mọi thứ diễn ra đúng, bạn sẽ nhận được một phản hồi tương tự như sau:

$ mongo --version
MongoDB shell version v3.6.8
git version: 8e540c0b6db93ce994cc548f000900bdc740f80a
OpenSSL version: OpenSSL 1.1.1f  31 Mar 2020
allocator: tcmalloc
modules: none
build environment:
    distarch: x86_64
    target_arch: x86_64

3. Bắt đầu MongoDB.

Để bắt đầu bạn hãy tạo thư mục chứa dữ liệu của MongoDB:

sudo mkdir -p /data/db

Bạn có thể khởi động MongoDB trên máy localhost của mình bằng lệnh mongod --port <port_number> . Hãy giữ cửa sổ mongod mở khi bạn muốn làm việc với MongoDB tại máy local của bạn. MongoDB sẽ dừng lại khi bạn đóng cửa sổ terminal này.

Bạn có thể sử dụng lệnh netstat -tlnp | grep mongod sẽ thấy port 27017 của Mongod đã bị chiếm dụng bởi service khởi động mặc định của MongoDB.

$ netstat -tlnp | grep mongod
tcp        0      0 127.0.0.1:27017         0.0.0.0:*               LISTEN      10251/mongod

Do port --port 27017 là port mặc định đã được listen rồi nên nếu mình dùng lại port này sẽ bị báo trùng port, nên giờ mình sẽ change port thành --port 27018.

$ mongod --port 27018
2023-11-13T12:02:09.856+0000 I CONTROL  [initandlisten] MongoDB starting : pid=10619 port=27018 dbpath=/data/db 64-bit host=docker-13-244
2023-11-13T12:02:09.857+0000 I CONTROL  [initandlisten] db version v3.6.8
2023-11-13T12:02:09.857+0000 I CONTROL  [initandlisten] git version: 8e540c0b6db93ce994cc548f000900bdc740f80a
2023-11-13T12:02:09.857+0000 I CONTROL  [initandlisten] OpenSSL version: OpenSSL 1.1.1f  31 Mar 2020
2023-11-13T12:02:09.857+0000 I CONTROL  [initandlisten] allocator: tcmalloc
2023-11-13T12:02:09.857+0000 I CONTROL  [initandlisten] modules: none
2023-11-13T12:02:09.857+0000 I CONTROL  [initandlisten] build environment:
2023-11-13T12:02:09.857+0000 I CONTROL  [initandlisten]     distarch: x86_64
2023-11-13T12:02:09.857+0000 I CONTROL  [initandlisten]     target_arch: x86_64
2023-11-13T12:02:09.857+0000 I CONTROL  [initandlisten] options: { net: { port: 27018 } }
2023-11-13T12:02:09.857+0000 I -        [initandlisten] Detected data files in /data/db created by the 'wiredTiger' storage engine, so setting the active storage engine to 'wiredTiger'.
2023-11-13T12:02:09.857+0000 I STORAGE  [initandlisten]
2023-11-13T12:02:09.857+0000 I STORAGE  [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine
2023-11-13T12:02:09.857+0000 I STORAGE  [initandlisten] **          See http://dochub.mongodb.org/core/prodnotes-filesystem
2023-11-13T12:02:09.857+0000 I STORAGE  [initandlisten] wiredtiger_open config: create,cache_size=1447M,session_max=20000,eviction=(threads_min=4,threads_max=4),config_base=false,statistics=(fast),cache_cursors=false,compatibility=(release="3.0",require_max="3.0"),log=(enabled=true,archive=true,path=journal,compressor=snappy),file_manager=(close_idle_time=100000),statistics_log=(wait=0),verbose=(recovery_progress),
2023-11-13T12:02:11.014+0000 I STORAGE  [initandlisten] WiredTiger message [1699876931:14029][10619:0x7ff7b127cac0], txn-recover: Main recovery loop: starting at 1/20864
2023-11-13T12:02:11.134+0000 I STORAGE  [initandlisten] WiredTiger message [1699876931:134236][10619:0x7ff7b127cac0], txn-recover: Recovering log 1 through 2
2023-11-13T12:02:11.304+0000 I STORAGE  [initandlisten] WiredTiger message [1699876931:304171][10619:0x7ff7b127cac0], txn-recover: Recovering log 2 through 2
2023-11-13T12:02:11.364+0000 I STORAGE  [initandlisten] WiredTiger message [1699876931:364309][10619:0x7ff7b127cac0], txn-recover: Set global recovery timestamp: 0
2023-11-13T12:02:11.972+0000 I CONTROL  [initandlisten]
2023-11-13T12:02:11.972+0000 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.
2023-11-13T12:02:11.972+0000 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.
2023-11-13T12:02:11.972+0000 I CONTROL  [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended.
2023-11-13T12:02:11.972+0000 I CONTROL  [initandlisten]
2023-11-13T12:02:11.972+0000 I CONTROL  [initandlisten] ** WARNING: This server is bound to localhost.
2023-11-13T12:02:11.972+0000 I CONTROL  [initandlisten] **          Remote systems will be unable to connect to this server.
2023-11-13T12:02:11.972+0000 I CONTROL  [initandlisten] **          Start the server with --bind_ip <address> to specify which IP
2023-11-13T12:02:11.972+0000 I CONTROL  [initandlisten] **          addresses it should serve responses from, or with --bind_ip_all to
2023-11-13T12:02:11.972+0000 I CONTROL  [initandlisten] **          bind to all interfaces. If this behavior is desired, start the
2023-11-13T12:02:11.972+0000 I CONTROL  [initandlisten] **          server with --bind_ip 127.0.0.1 to disable this warning.
2023-11-13T12:02:11.972+0000 I CONTROL  [initandlisten]
2023-11-13T12:02:11.986+0000 I FTDC     [initandlisten] Initializing full-time diagnostic data capture with directory '/data/db/diagnostic.data'
2023-11-13T12:02:11.987+0000 I NETWORK  [initandlisten] waiting for connections on port 27018

Nếu bạn gặp lỗi exception in initAndListen: NonExistentPath: Data directory /data/db not found., terminating như dưới. Điều này có nghĩa là MongoDB không thể tìm thấy thư mục dữ liệu (/data/db) để lưu trữ dữ liệu. Trước khi bạn chạy lệnh mongod, hãy chắc chắn rằng thư mục dữ liệu đã được tạo. MongoDB sẽ không tự tạo thư mục này nếu nó không tồn tại.

$ mongod --port 27018
2023-11-13T06:34:22.276+0000 I CONTROL  [initandlisten] MongoDB starting : pid=6691 port=27017 dbpath=/data/db 64-bit host=docker-13-244
2023-11-13T06:34:22.276+0000 I CONTROL  [initandlisten] db version v3.6.8
2023-11-13T06:34:22.276+0000 I CONTROL  [initandlisten] git version: 8e540c0b6db93ce994cc548f000900bdc740f80a
2023-11-13T06:34:22.276+0000 I CONTROL  [initandlisten] OpenSSL version: OpenSSL 1.1.1f  31 Mar 2020
2023-11-13T06:34:22.276+0000 I CONTROL  [initandlisten] allocator: tcmalloc
2023-11-13T06:34:22.276+0000 I CONTROL  [initandlisten] modules: none
2023-11-13T06:34:22.276+0000 I CONTROL  [initandlisten] build environment:
2023-11-13T06:34:22.276+0000 I CONTROL  [initandlisten]     distarch: x86_64
2023-11-13T06:34:22.276+0000 I CONTROL  [initandlisten]     target_arch: x86_64
2023-11-13T06:34:22.276+0000 I CONTROL  [initandlisten] options: {}
2023-11-13T06:34:22.277+0000 I STORAGE  [initandlisten] exception in initAndListen: NonExistentPath: Data directory /data/db not found., terminating
2023-11-13T06:34:22.277+0000 I CONTROL  [initandlisten] now exiting
2023-11-13T06:34:22.277+0000 I CONTROL  [initandlisten] shutting down with code:100

Lưu ý rằng đối với một số hệ điều hành, bạn có thể cần chạy lệnh trên với quyền quản trị (sudo). Sau khi tạo xong, thử chạy lại lệnh mongod. Nếu vấn đề vẫn tiếp tục, đảm bảo rằng bạn có quyền ghi vào thư mục bạn đã chọn làm thư mục dữ liệu.

4. Tổng quan ngắn gọn về cách hoạt động của MongoDB.

MongoDB là một hệ quản trị cơ sở dữ liệu (DBMS) thuộc loại NoSQL, cho phép lưu trữ các đối tượng gọi là documents trong cơ sở dữ liệu. Cơ sở dữ liệu này được tổ chức thành các đơn vị lớn hơn, bao gồm nhiều multiple collections.

để giải thích một cách dễ hiểu hơn, hãy xem xét một ví dụ về cách MongoDB tổ chức dữ liệu. Giả sử chúng ta đang quản lý thông tin về một thư viện sách:

  • Tòa nhà MongoDB:
    • MongoDB là tòa nhà chứa mọi thứ, giống như một hệ thống quản lý cơ sở dữ liệu.
  • Phòng (Databases) trong Tòa nhà:
    • Các phòng trong tòa nhà có thể được xem xét như các cơ sở dữ liệu. Mỗi phòng (cơ sở dữ liệu) chứa thông tin liên quan đến một loại dữ liệu cụ thể. Ví dụ, có thể có một phòng cho sách, một phòng cho người dùng, và một phòng cho đơn đặt hàng.
  • Hộp (Collections) trong Mỗi Phòng:
    • Trong mỗi phòng, có nhiều hộp, mỗi hộp tương ứng với một loại dữ liệu cụ thể. Ví dụ, hộp trong phòng sách có thể là “Tất cả Sách,” hộp trong phòng người dùng có thể là “Tất cả Người Dùng.”
  • Tài Liệu (Documents) trong Mỗi Hộp:
    • Trong mỗi hộp, có nhiều tài liệu. Mỗi tài liệu tương ứng với một bản ghi dữ liệu cụ thể. Ví dụ, tài liệu trong hộp “Tất cả Sách” có thể là thông tin về một cuốn sách cụ thể, bao gồm tiêu đề, tác giả, và số lượng.
  • Ví Dụ Cụ Thể:
    • Ví dụ, trong phòng “Sách,” bạn có một hộp có tên là “Tất cả Sách” và trong hộp đó, bạn có tài liệu với thông tin của mỗi cuốn sách như “Tiêu đề,” “Tác giả,” và “Năm xuất bản.”
{
  "Tiêu đề": "Làm quen với MongoDB",
  "Tác giả": "Hà Đăng Hoàng",
  "Năm xuất bản": 2022
}
  • Mỗi tài liệu trong hộp “Tất cả Sách” chứa thông tin về một cuốn sách cụ thể.

5. Thêm dữ liệu vào MongoDB.

Bước 1 – Một cách để thêm dữ liệu vào cơ sở dữ liệu MongoDB là thông qua Mongo Shell. Để mở Mongo Shell, bạn mở một cửa sổ terminal và chạy lệnh mongo(nếu bạn còn giữ terminal này ở phần trên thì không cần chạy lại nữa).

mongod --port 27018

Lưu ý: Đảm bảo bạn giữ cửa sổ mongod mở! Bạn sẽ không thể tương tác với Mongo Shell nếu bạn đóng cửa sổ mongod.

Bước 2 – Chọn hoặc Tạo Cơ Sở Dữ Liệu:

Bạn hãy mở một terminal mới và gõ vào mongo, bạn sẽ nhận được dấu nhắc > ở dòng dưới cùng của terminal.

$ mongo
MongoDB shell version v3.6.8
connecting to: mongodb://127.0.0.1:27017
Implicit session: session { "id" : UUID("266e0352-d978-4c55-a730-d751ef1f7263") }
MongoDB server version: 3.6.8
Server has startup warnings:
2023-11-13T11:57:16.995+0000 I STORAGE  [initandlisten]
2023-11-13T11:57:16.995+0000 I STORAGE  [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine
2023-11-13T11:57:16.995+0000 I STORAGE  [initandlisten] **          See http://dochub.mongodb.org/core/prodnotes-filesystem
2023-11-13T11:57:19.305+0000 I CONTROL  [initandlisten]
2023-11-13T11:57:19.305+0000 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.
2023-11-13T11:57:19.305+0000 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.
2023-11-13T11:57:19.305+0000 I CONTROL  [initandlisten]
>

Chúng ta cần một cơ sở dữ liệu để làm việc. Bạn có thể xem cơ sở dữ liệu hiện tại được chọn bằng lệnh db. (Mặc định, bạn sẽ đang ở cơ sở dữ liệu test).

> db
test
  • Lưu ý: Dấu > trong output trên biểu thị Mongo Shell. Bạn không cần gõ >, nó không phải là một phần của lệnh.
  • Terminal sẽ trả về ‘test’ khi bạn chạy lệnh ‘db’.

Bước 3 – Tạo và chuyển đến một DB:

  • Trong ví dụ này, chúng ta sẽ tạo một cơ sở dữ liệu có tên là “game-of-thrones”. Bạn có thể sử dụng lệnh use <tên cơ sở dữ liệu> để tạo và chuyển đến một cơ sở dữ liệu mới.
> use game-of-thrones
switched to db game-of-thrones

Shell sẽ hiển thị “Switched to db game-of-thrones” để xác nhận bạn đã chuyển đến cơ sở dữ liệu mới.

Bước 4 – Để insert dữ liệu vào DB, bạn có thể truyền một đối tượng JavaScript vào db.<tên bộ sưu tập>.insertOne().

> db.characters.insertOne({ name: 'Jon Snow' })
{
        "acknowledged" : true,
        "insertedId" : ObjectId("655211119926ee765f9f2ced")
}
>

Shell sẽ hiển thị thông báo “Added ‘Jon Snow’ into the ‘characters’ collection.”

Hãy thêm một nhân vật khác vào cơ sở dữ liệu trước khi chúng ta tiếp tục.

> db.characters.insertOne({ name: 'Arya Stark' })
{
        "acknowledged" : true,
        "insertedId" : ObjectId("6552112b9926ee765f9f2cee")
}
>

Shell sẽ hiển thị thông báo “Added ‘Arya Stark’ into the ‘characters’ collection.”

Bạn có thể xem những nhân vật mà chúng ta đã thêm bằng cách sử dụng lệnh find. (db.<tên bộ sưu tập>.find()).

> db.characters.find()
{ "_id" : ObjectId("655211119926ee765f9f2ced"), "name" : "Jon Snow" }
{ "_id" : ObjectId("6552112b9926ee765f9f2cee"), "name" : "Arya Stark" }
>

Cơ sở dữ liệu sẽ trả về hai nhân vật: ‘Jon Snow’ và ‘Arya Stark’ và tạm thời đó là tất cả những gì bạn cần biết về Mongo Shell.

6. Sử dụng tool bên ngoài để kết nối vào MongoDB.

Để cho phép kết nối từ tất cả các địa chỉ IP hoặc một địa chỉ IP cụ thể khác 127.0.0.1 (localhost), bạn cần chỉnh sửa cấu hình của MongoDB. Mặc định, MongoDB chỉ lắng nghe kết nối từ localhost (127.0.0.1).

$ netstat -tlnp | grep mongo
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:27017         0.0.0.0:*               LISTEN      6886/mongod

Mở file cấu hình của MongoDB vi /etc/mongodb.conf . Đường dẫn có thể khác nhau tùy thuộc vào hệ điều hành và cách bạn đã cài đặt MongoD, tìm và Sửa Dòng bindIp.

bind_ip = 127.0.0.1

Sửa thành bind_ip = 0.0.0.0 để cho tất cả các IP kết nối vào MongoDB.

bindIp: 0.0.0.0

hoặc để chỉ cho phép một địa chỉ IP cụ thể:

bindIp: your_specific_ip

Sau khi chỉnh sửa cấu hình, bạn cần khởi động lại dịch vụ MongoDB để áp dụng thay đổi.

sudo systemctl restart mongodb

Kiểm tra lại kết nối với netstat để đảm bảo MongoDB đang lắng nghe trên tất cả địa chỉ IP hoặc địa chỉ IP cụ thể bạn đã chỉ định.

$ netstat -tlnp | grep mongo
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:27017           0.0.0.0:*               LISTEN      7152/mongo

Để kết nối vào MongoDB từ một công cụ ngoại vi như Navicat, bạn cần biết thông tin như địa chỉ IP của máy chủ MongoDB, cổng kết nối (mặc định là 27017) và tên cơ sở dữ liệu.

Điền Thông Tin Kết Nối:

  • Điền các thông tin kết nối vào các trường cần thiết:
    • Connection Name: Tên kết nối (đặt tên bạn muốn).
    • Host Address: Địa chỉ IP hoặc tên máy chủ của MongoDB.
    • Port: Cổng kết nối MongoDB (mặc định là 27017).
    • Username và Password: Nếu bạn đã bật xác thực trên MongoDB.
    • Database: Tên cơ sở dữ liệu bạn muốn kết nối.

Nhấn nút “Test Connection” để kiểm tra xem Navicat có thể kết nối vào MongoDB không.Nhấn nút “Test Connection” để kiểm tra xem Navicat có thể kết nối vào MongoDB không.

Sau khi kiểm tra kết nối thành công, nhấn “Save” hoặc “Connect” để lưu cấu hình và kết nối vào cơ sở dữ liệu MongoDB.

Sau những bước này, bạn sẽ có thể quản lý cơ sở dữ liệu MongoDB của mình từ Navicat hoặc bất kỳ công cụ quản lý cơ sở dữ liệu nào khác mà bạn đã cấu hình.

7. Xác thực username và password trong MongoDB.

Để bật xác thực username và password trong MongoDB, bạn cần thực hiện các bước sau:

Bước 1 – Chạy MongoDB với tùy chọn xác thực:

Khi bạn khởi động mongod (dịch vụ MongoDB), bạn cần thêm tùy chọn --auth để bật xác thực. Bạn cũng có thể chỉ tạo hoặc định một thư mục đã tạo trước đó (ví dụ /data/db) để lưu trữ các thông tin xác thực. Do port 27017 tôi đã sử dụng nên tôi sẽ đổi qua port 27018.

$ mongod --auth --dbpath /data/db --port 27018
2023-11-13T08:51:06.150+0000 I CONTROL  [initandlisten] MongoDB starting : pid=8014 port=27018 dbpath=/data/db 64-bit host=docker-13-244
2023-11-13T08:51:06.150+0000 I CONTROL  [initandlisten] db version v3.6.8
2023-11-13T08:51:06.150+0000 I CONTROL  [initandlisten] git version: 8e540c0b6db93ce994cc548f000900bdc740f80a
2023-11-13T08:51:06.150+0000 I CONTROL  [initandlisten] OpenSSL version: OpenSSL 1.1.1f  31 Mar 2020
2023-11-13T08:51:06.150+0000 I CONTROL  [initandlisten] allocator: tcmalloc
2023-11-13T08:51:06.150+0000 I CONTROL  [initandlisten] modules: none
2023-11-13T08:51:06.150+0000 I CONTROL  [initandlisten] build environment:
2023-11-13T08:51:06.150+0000 I CONTROL  [initandlisten]     distarch: x86_64
2023-11-13T08:51:06.150+0000 I CONTROL  [initandlisten]     target_arch: x86_64
2023-11-13T08:51:06.150+0000 I CONTROL  [initandlisten] options: { net: { port: 27018 }, security: { authorization: "enabled" }, storage: { dbPath: "/data/db" } }
2023-11-13T08:51:06.150+0000 I -        [initandlisten] Detected data files in /data/db created by the 'wiredTiger' storage engine, so setting the active storage engine to 'wiredTiger'.
2023-11-13T08:51:06.150+0000 I STORAGE  [initandlisten]
2023-11-13T08:51:06.150+0000 I STORAGE  [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine
2023-11-13T08:51:06.150+0000 I STORAGE  [initandlisten] **          See http://dochub.mongodb.org/core/prodnotes-filesystem
2023-11-13T08:51:06.150+0000 I STORAGE  [initandlisten] wiredtiger_open config: create,cache_size=1447M,session_max=20000,eviction=(threads_min=4,threads_max=4),config_base=false,statistics=(fast),cache_cursors=false,compatibility=(release="3.0",require_max="3.0"),log=(enabled=true,archive=true,path=journal,compressor=snappy),file_manager=(close_idle_time=100000),statistics_log=(wait=0),verbose=(recovery_progress),
2023-11-13T08:51:07.283+0000 I STORAGE  [initandlisten] WiredTiger message [1699865467:283423][8014:0x7f5aeb00dac0], txn-recover: Main recovery loop: starting at 3/5376
2023-11-13T08:51:07.402+0000 I STORAGE  [initandlisten] WiredTiger message [1699865467:402166][8014:0x7f5aeb00dac0], txn-recover: Recovering log 3 through 4
2023-11-13T08:51:07.578+0000 I STORAGE  [initandlisten] WiredTiger message [1699865467:578148][8014:0x7f5aeb00dac0], txn-recover: Recovering log 4 through 4
2023-11-13T08:51:07.638+0000 I STORAGE  [initandlisten] WiredTiger message [1699865467:638151][8014:0x7f5aeb00dac0], txn-recover: Set global recovery timestamp: 0
2023-11-13T08:51:08.217+0000 I CONTROL  [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended.
2023-11-13T08:51:08.217+0000 I CONTROL  [initandlisten]
2023-11-13T08:51:08.217+0000 I CONTROL  [initandlisten] ** WARNING: This server is bound to localhost.
2023-11-13T08:51:08.217+0000 I CONTROL  [initandlisten] **          Remote systems will be unable to connect to this server.
2023-11-13T08:51:08.217+0000 I CONTROL  [initandlisten] **          Start the server with --bind_ip <address> to specify which IP
2023-11-13T08:51:08.217+0000 I CONTROL  [initandlisten] **          addresses it should serve responses from, or with --bind_ip_all to
2023-11-13T08:51:08.217+0000 I CONTROL  [initandlisten] **          bind to all interfaces. If this behavior is desired, start the
2023-11-13T08:51:08.217+0000 I CONTROL  [initandlisten] **          server with --bind_ip 127.0.0.1 to disable this warning.
2023-11-13T08:51:08.217+0000 I CONTROL  [initandlisten]
2023-11-13T08:51:08.233+0000 I FTDC     [initandlisten] Initializing full-time diagnostic data capture with directory '/data/db/diagnostic.data'
2023-11-13T08:51:08.234+0000 I NETWORK  [initandlisten] waiting for connections on port 27018

Bước 2 – Tạo người dùng quản trị.

Trước tiên, hãy chắc chắn rằng MongoDB đã được khởi động. Bạn có thể sử dụng lệnh mongod để bắt đầu MongoDB server.

Mở một cửa sổ terminal mới và chạy lệnh sau để kết nối vào MongoDB:

$ mongo
MongoDB shell version v3.6.8
connecting to: mongodb://127.0.0.1:27017
Implicit session: session { "id" : UUID("f66b50ad-2b5b-4c0b-89bf-cbbcdc5a9d54") }
MongoDB server version: 3.6.8
Server has startup warnings:
2023-11-13T12:07:26.131+0000 I STORAGE  [initandlisten]
2023-11-13T12:07:26.131+0000 I STORAGE  [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine
2023-11-13T12:07:26.131+0000 I STORAGE  [initandlisten] **          See http://dochub.mongodb.org/core/prodnotes-filesystem
2023-11-13T12:07:28.432+0000 I CONTROL  [initandlisten]
2023-11-13T12:07:28.432+0000 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.
2023-11-13T12:07:28.432+0000 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.
2023-11-13T12:07:28.432+0000 I CONTROL  [initandlisten]
>

Chuyển đến cơ sở dữ liệu “admin” bằng cách chạy lệnh:

use admin

Tạo một người dùng quản trị với lệnh sau:

db.createUser({
  user: "adminUser",
  pwd: "adminPassword",
  roles: ["root"]
})

Đổi “adminUser” thành tên người dùng bạn muốn và “adminPassword” thành mật khẩu bạn muốn sử dụng. Ví dụ:

> use admin
switched to db admin
> db.createUser({
...   user: "hoanghd",
...   pwd: "Hoanghd164",
...   roles: ["root"]
... })
Successfully added user: { "user" : "hoanghd", "roles" : [ "root" ] }
>

Xác thực bằng tài khoản quản trị bạn vừa tạo:

db.auth("adminUser", "adminPassword")

Nếu bạn xác thực thành công, bạn sẽ thấy một thông báo xác nhận.

> db.auth("hoanghd", "Hoanghd164")
1

Sau những bước này, bạn đã tạo một người dùng quản trị và xác thực với nó. Bây giờ, bạn có thể sử dụng tài khoản này để thêm người dùng khác hoặc thực hiện các công việc quản trị khác trên MongoDB của mình. Lưu ý rằng trong môi trường thực tế, bạn nên thiết lập mật khẩu mạnh hơn và quản lý người dùng một cách an toàn.

Bước 3 – Bật xác Thực trong file config của MongoDB.

Đảm bảo rằng xác thực đã được bật trong cấu hình MongoDB. Bạn có thể kiểm tra file cấu hình (vi /etc/mongodb.conf) để đảm bảo rằng auth = true.

Sau đó khởi động lại MongoDB.

sudo systemctl restart mongodb

Bạn cần kết nối vào MongoDB và tạo người dùng có tên và mật khẩu để sử dụng khi kết nối từ các công cụ khác như Navicat. Nếu bạn không xác thực bạn sẽ gặp lỗi như dưới.

Ví dụ, để cho phép người dùng “yourUsername” đọc và ghi tất cả các cơ sở dữ liệu, bạn có thể thêm quyền với roleuserAdminAnyDatabase như sau:

db.createUser({
  user: "yourUsername",
  pwd: "yourPassword",
  roles: ["userAdminAnyDatabase", "dbAdminAnyDatabase", "readWriteAnyDatabase", "clusterAdmin"]
})

Trong đoạn output trên, thay "yourUsername""yourPassword" bằng thông tin xác thực bạn muốn sử dụng. Ví dụ:

> use admin
switched to db admin
> db.auth("hoanghd", "Hoanghd164")
1
> db.dropUser("yourUsername")
true
> db.createUser({
...   user: "yourUsername",
...   pwd: "yourPassword",
...   roles: ["userAdminAnyDatabase", "dbAdminAnyDatabase", "readWriteAnyDatabase", "clusterAdmin"]
... })
Successfully added user: {
        "user" : "yourUsername",
        "roles" : [
                "userAdminAnyDatabase",
                "dbAdminAnyDatabase",
                "readWriteAnyDatabase",
                "clusterAdmin"
        ]
}
>

Lưu ý rằng “readWrite” là một quyền phổ biến cho việc đọc và ghi dữ liệu trong một cơ sở dữ liệu cụ thể.

Bạn phải chạy lệnh db.auth(“hoanghd”, “Hoanghd164”) để xác thực username admin trước khi chạy lệnh tạo mới username nhé. Nếu không bạn sẽ gặp lỗi như dưới.

> use admin
switched to db admin
> db.createUser(
...   {
...     user: "yourUsername",
...     pwd: "yourPassword",
...     roles: [
...       { role: "userAdminAnyDatabase", db: "admin" }
...     ]
...   }
... )
2023-11-13T12:16:11.470+0000 E QUERY    [thread1] Error: couldn't add user: there are no users authenticated :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
DB.prototype.createUser@src/mongo/shell/db.js:1437:15
@(shell):1:1

Sau khi tạo người dùng, bạn có thể sử dụng thông tin đăng nhập của người dùng này để truy cập và thao tác với các cơ sở dữ liệu các quyền đã được xác định.

Để liệt kê danh sách người dùng trong MongoDB, bạn có thể sử dụng một trong những cách sau:

> show users
{
        "_id" : "admin.hoanghd",
        "userId" : UUID("db62bf98-0f23-4e50-b851-170260500375"),
        "user" : "hoanghd",
        "db" : "admin",
        "roles" : [
                {
                        "role" : "root",
                        "db" : "admin"
                }
        ]
}
{
        "_id" : "admin.yourUsername",
        "userId" : UUID("2c9ebedc-4905-46be-a3a6-d212cfeb0b75"),
        "user" : "yourUsername",
        "db" : "admin",
        "roles" : [
                {
                        "role" : "userAdminAnyDatabase",
                        "db" : "admin"
                },
                {
                        "role" : "dbAdminAnyDatabase",
                        "db" : "admin"
                },
                {
                        "role" : "readWriteAnyDatabase",
                        "db" : "admin"
                },
                {
                        "role" : "clusterAdmin",
                        "db" : "admin"
                }
        ]
}
>
  • Kết nối MongoDB với tài khoản xác thực đã tạo:
    • Khi bạn kết nối từ Navicat hoặc bất kỳ công cụ quản lý cơ sở dữ liệu nào khác, hãy sử dụng thông tin xác thực mà bạn đã tạo ở bước trước.
    • Điền thông tin như tên người dùng, mật khẩu, địa chỉ IP, cổng và cơ sở dữ liệu.
    • Kiểm tra kết nối để đảm bảo thông tin xác thực của bạn là chính xác.

Kết quả.

Với quyền này thì username yourUsername được phép đọc toàn bộ DB đang tồn tại nhé.

Lưu ý rằng xác thực có thể được kích hoạt cho cơ sở dữ liệu cụ thể (thay vì toàn bộ hệ thống) bằng cách chỉ định database trong tùy chọn db.createUser. Điều này hữu ích khi bạn muốn quản lý quyền truy cập của người dùng đối với một cơ sở dữ liệu cụ thể.

8. Tạo một người dùng với quyền truy cập chỉ vào một cơ sở dữ liệu cụ thể.

Để tạo một người dùng với quyền truy cập chỉ vào một cơ sở dữ liệu cụ thể trong MongoDB, bạn có thể thực hiện các bước sau:

Mở MongoDB Shell bằng cách chạy lệnh mongo trong terminal hoặc command prompt.

Sử dụng lệnh use để chọn cơ sở dữ liệu mà bạn muốn người dùng có quyền truy cập. Trong trường hợp của bạn, đó là devops.

> use devops
switched to db devops
> db.testCollection.insert({key: "value"})
WriteResult({ "nInserted" : 1 })

Sử dụng lệnh db.createUser() để tạo một người dùng với quyền truy cập chỉ vào cơ sở dữ liệu hiện tại.

db.createUser(
  {
    user: "yourUsername1",
    pwd: "yourPassword",
    roles: [ { role: "readWrite", db: "devops" } ]
  }
)

Sử dụng lệnh db.getUsers() để kiểm tra xem người dùng đã được tạo thành công hay không.

> db.getUsers()
[
        {
                "_id" : "devops.yourUsername1",
                "userId" : UUID("8a81c143-8517-4fac-9d0f-9c3aa5f521e1"),
                "user" : "yourUsername1",
                "db" : "devops",
                "roles" : [
                        {
                                "role" : "readWrite",
                                "db" : "devops"
                        }
                ]
        }
]

Nếu người dùng yourUsername1 xuất hiện trong danh sách, người dùng đã được tạo thành công với quyền truy cập chỉ vào cơ sở dữ liệu devops.

Lưu ý rằng quyền readWrite ở đây cho phép người dùng đọc và ghi dữ liệu trong cơ sở dữ liệu game-of-thrones. Nếu bạn chỉ muốn người dùng có quyền đọc (read) mà không có quyền ghi, bạn có thể sử dụng read thay vì readWrite.

Nếu bạn chỉ điền thông tin username/password nhưng bỏ trống Authentication Database.

Kết quả bạn sẽ không thể login vào DB được.

Nếu bạn điền tên DB đã được phân quyền thì kết quả sẽ thành công.

Kết quả.

Khi login vào bạn chỉ thấy db devops mà bạn đã phân quyền cho username yourUsername1 được phép truy cập, còn game-of-thrones mình đã tạo ở đầu bài hoàn toàn không xuất hiện trong danh sách này.

9. Cập nhật người dùng trong MongoDB.

Để cập nhật người dùng yourUsername1 để có quyền truy cập vào cả hai cơ sở dữ liệu game-of-thronesdevops, bạn có thể thực hiện các bước sau:

Mở MongoDB Shell bằng cách chạy lệnh mongo trong terminal hoặc command prompt.

Sử dụng lệnh use admin để chọn cơ sở dữ liệu admin.

Xác thực quyền admin bằng lệnh db.auth("hoanghd", "Hoanghd164").

use admin
db.auth("hoanghd", "Hoanghd164")

Lựa chọn DB mà bạn muốn cập nhật (lưu ý người dùng này phải được tạo cho DB từ trước nhé).

use game-of-thrones

Sử dụng lệnh db.updateUser() để cập nhật người dùng yourUsername1 và thêm quyền truy cập vào game-of-thrones.

db.updateUser(
  "yourUsername1",
  {
    roles: [
      { role: "readWrite", db: "game-of-thrones" },
      { role: "readWrite", db: "devops" }
    ]
  }
)

Output mà bạn nhận được là.

> use game-of-thrones
switched to db game-of-thrones
> game-of-thrones
2023-11-13T12:45:19.092+0000 E QUERY    [thread1] ReferenceError: game is not defined :
@(shell):1:1
> db.updateUser(
...   "yourUsername1",
...   {
...     roles: [
...       { role: "readWrite", db: "game-of-thrones" },
...       { role: "readWrite", db: "devops" }
...     ]
...   }
... )
>

Nếu bạn không muốn giữ nguyên các quyền trước đó của người dùng (ví dụ: chỉ muốn quyền readWrite trên game-of-thronesdb-test), bạn cũng có thể sử dụng lệnh db.grantRolesToUser().

db.grantRolesToUser(
  "yourUsername1",
  [
    { role: "readWrite", db: "game-of-thrones" },
    { role: "readWrite", db: "devops" }
  ]
)

Sử dụng lệnh db.getUser() để kiểm tra xem người dùng đã được cập nhật thành công hay không.

db.getUser("yourUsername1")

Output bạn sẽ nhận được.

> db.getUser("yourUsername1")
{
        "_id" : "game-of-thrones.yourUsername1",
        "userId" : UUID("44a6359b-8858-4813-8605-925c03034c17"),
        "user" : "yourUsername1",
        "db" : "game-of-thrones",
        "roles" : [
                {
                        "role" : "readWrite",
                        "db" : "game-of-thrones"
                },
                {
                        "role" : "readWrite",
                        "db" : "devops"
                }
        ]
}
>

Kiểm tra xem quyền truy cập vào cơ sở dữ liệu devops có được thêm vào hay không.

Sau khi thực hiện các bước trên, người dùng yourUsername1 nên có quyền truy cập vào cả hai cơ sở dữ liệu game-of-thronesdevops.

Kết quả.

Đây là dữ liệu của DB game-of-thrones mà username yourUsername1 đã xem được.

10. Xóa quyền trong Username.

Để xóa quyền của người dùng yourUsername1 khỏi cơ sở dữ liệu game-of-thrones trong MongoDB, bạn có thể sử dụng lệnh db.revokeRolesFromUser() như sau:

db.revokeRolesFromUser(
  "yourUsername1",
  [
    { role: "readWrite", db: "game-of-thrones" }
  ]
)

Lưu ý nhớ lựa chọn DB game-of-thrones rồi mới thực hiện xóa quyền nhé.

Show kết quả bằng lệnh db.getUser(“yourUsername1“).

> db.getUser("yourUsername1")
{
        "_id" : "game-of-thrones.yourUsername1",
        "userId" : UUID("44a6359b-8858-4813-8605-925c03034c17"),
        "user" : "yourUsername1",
        "db" : "game-of-thrones",
        "roles" : [
                {
                        "role" : "readWrite",
                        "db" : "devops"
                }
        ]
}

Giờ nếu bạn reload lại Navicat bạn sẽ không còn quyền đọc dữ liệu tại DB game-of-thrones nữa.

11. Xóa một người dùng trong MongoDB.

Để xóa một người dùng trong MongoDB, bạn có thể sử dụng lệnh db.dropUser() trong MongoDB Shell.

use admin
db.dropUser("yourUsername")

Thay "yourUsername" bằng tên người dùng bạn muốn xóa.

Lưu ý, bạn cần có quyền userAdminAnyDatabase hoặc tương đương để thực hiện lệnh này và việc xóa một người dùng sẽ ngăn chặn họ khỏi việc đăng nhập vào cơ sở dữ liệu. Hãy đảm bảo rằng bạn muốn thực hiện hành động này và xác nhận rằng người dùng đó không còn cần thiết cho hệ thống của bạn trước khi xóa.

12. Một số lưu ý.

Trong MongoDB, các tài khoản người dùng được quản lý ở mức cơ sở dữ liệu (database) chứ không phải ở mức toàn bộ hệ thống. Điều này có nghĩa là bạn có thể có cùng tên người dùng (username) trong nhiều cơ sở dữ liệu khác nhau mà không gây xung đột.

Khi bạn tạo một người dùng trong một cơ sở dữ liệu cụ thể, thông tin người dùng đó chỉ áp dụng cho cơ sở dữ liệu đó. Ví dụ, nếu bạn có người dùng “hoanghd” trong cơ sở dữ liệu “db1”, bạn vẫn có thể tạo một người dùng khác cùng tên “hoanghd” trong cơ sở dữ liệu “db2” mà không gặp xung đột.

Dưới đây là một ví dụ về cách tạo người dùng trong MongoDB cho các cơ sở dữ liệu khác nhau:

// Tạo người dùng trong cơ sở dữ liệu db1
use db1
db.createUser({
  user: "hoanghd",
  pwd: "password123",
  roles: ["readWrite"]
})

// Tạo người dùng trong cơ sở dữ liệu db2
use db2
db.createUser({
  user: "hoanghd",
  pwd: "anotherPassword",
  roles: ["readWrite"]
})

Ở đây, ta đã tạo một người dùng “hoanghd” trong cơ sở dữ liệu “db1” và một người dùng khác cũng tên “hoanghd” trong cơ sở dữ liệu “db2” mà không gây xung đột.

Nếu bạn muốn tạo một người dùng có quyền truy cập toàn bộ hệ thống MongoDB, bạn cần tạo người dùng đó ở mức cơ sở dữ liệu “admin”. Người dùng này sau đó có thể sử dụng thông tin đăng nhập để truy cập mọi cơ sở dữ liệu trong hệ thống.

Dưới đây là cách tạo một người dùng toàn hệ thống:

Kết nối vào MongoDB và chuyển đến cơ sở dữ liệu “admin”:

use admin

Tạo người dùng với quyền toàn hệ thống:

db.createUser({
  user: "hoanghd",
  pwd: "password123",
  roles: ["userAdminAnyDatabase", "dbAdminAnyDatabase", "readWriteAnyDatabase", "clusterAdmin"]
})
  • Trong ví dụ này, người dùng “hoanghd” sẽ có các quyền như sau:
    • userAdminAnyDatabase: Quyền quản trị người dùng cho mọi cơ sở dữ liệu.
    • dbAdminAnyDatabase: Quyền quản trị cơ sở dữ liệu cho mọi cơ sở dữ liệu.
    • readWriteAnyDatabase: Quyền đọc và ghi cho mọi cơ sở dữ liệu.
    • clusterAdmin: Quyền quản trị cụm MongoDB (cluster).
  • Sau khi tạo xong, bạn có thể sử dụng tài khoản “hoanghd” để truy cập và thực hiện các thao tác trên mọi cơ sở dữ liệu trong hệ thống.

13. Một số công cụ khác.

Có một số công cụ CLI và GUI có thể bạn sử dụng để kết nối và quản lý MongoDB từ xa. Dưới đây là một số công cụ phổ biến:

  • Mongo Shell (CLI):
    • Mongo Shell là công cụ dòng lệnh chính thức của MongoDB.
    • Bạn có thể cài đặt MongoDB Shell trên máy tính của mình và kết nối đến cơ sở dữ liệu MongoDB từ xa.
    • Sử dụng lệnh sau để kết nối đến một máy chủ MongoDB từ xa:
mongosh --host <hostname> --port <port> --username <username> --password <password> --authenticationDatabase <authDB>

Đây là ví dụ với Mongo Shell chạy trên MacOS.

$ mongosh --host 192.168.13.244 --port 27017 --username hoanghd --password Hoanghd164
(node:4624) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
Current Mongosh Log ID:	65522564ea01f126ca664fd0
Connecting to:		mongodb://<credentials>@192.168.13.244:27017/?directConnection=true&appName=mongosh+2.0.2
Using MongoDB:		3.6.8
Using Mongosh:		2.0.2

For mongosh info see: https://docs.mongodb.com/mongodb-shell/

------
   The server generated these startup warnings when booting
   2023-11-13T12:13:18.667+0000:
   2023-11-13T12:13:18.667+0000: ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine
   2023-11-13T12:13:18.667+0000: **          See http://dochub.mongodb.org/core/prodnotes-filesystem
------

test> use admin
switched to db admin
admin> db.auth("hoanghd", "Hoanghd164")
{ ok: 1 }
admin> show users
[
  {
    _id: 'admin.hoanghd',
    userId: new UUID("db62bf98-0f23-4e50-b851-170260500375"),
    user: 'hoanghd',
    db: 'admin',
    roles: [ { role: 'root', db: 'admin' } ]
  },
  {
    _id: 'admin.test1',
    userId: new UUID("3eb7ad8a-5c5d-423c-90a3-ca415db11fa4"),
    user: 'test1',
    db: 'admin',
    roles: [
      { role: 'userAdminAnyDatabase', db: 'admin' },
      { role: 'dbAdminAnyDatabase', db: 'admin' },
      { role: 'readWriteAnyDatabase', db: 'admin' },
      { role: 'clusterAdmin', db: 'admin' }
    ]
  },
  {
    _id: 'admin.yourUsername',
    userId: new UUID("2c9ebedc-4905-46be-a3a6-d212cfeb0b75"),
    user: 'yourUsername',
    db: 'admin',
    roles: [
      { role: 'userAdminAnyDatabase', db: 'admin' },
      { role: 'dbAdminAnyDatabase', db: 'admin' },
      { role: 'readWriteAnyDatabase', db: 'admin' },
      { role: 'clusterAdmin', db: 'admin' }
    ]
  }
]
admin>
  • Robo 3T (GUI):
    • Robo 3T là một công cụ quản lý cơ sở dữ liệu MongoDB với giao diện đồ họa.
    • Bạn có thể tạo kết nối mới và cung cấp thông tin đăng nhập để kết nối đến máy chủ MongoDB từ xa.
  • MongoDB Compass (GUI):
    • MongoDB Compass là một công cụ quản lý cơ sở dữ liệu MongoDB với giao diện đồ họa.
    • Nó cung cấp giao diện trực quan để thực hiện các thao tác quản lý và truy vấn trên cơ sở dữ liệu.
    • Bạn có thể tạo kết nối mới và nhập thông tin đăng nhập để kết nối đến máy chủ MongoDB từ xa.
  • Navicat for MongoDB (GUI):
    • Navicat là một công cụ quản lý cơ sở dữ liệu phổ biến với hỗ trợ cho nhiều loại cơ sở dữ liệu, bao gồm MongoDB.
    • Bạn có thể tạo kết nối mới và nhập thông tin đăng nhập để kết nối đến máy chủ MongoDB từ xa.

Lưu ý rằng khi kết nối từ xa, bạn cần cung cấp đúng thông tin đăng nhập và xác thực cho MongoDB, và cần chắc chắn rằng cổng MongoDB (mặc định là 27017) không bị chặn bởi tường lửa hoặc các thiết lập bảo mật khác trên máy chủ MongoDB.

1 COMMENT

LEAVE A REPLY

Please enter your comment!
Please enter your name here

4,956FansLike
256FollowersFollow
223SubscribersSubscribe
spot_img

Related Stories