Mục lục
Để thao tác với MongoDB database việc trước hết là phải tạo một kết nối đến MongoDB. Mongoose#connect() method giúp chúng ta tạo một kết nối đến MongoDB, mặc định các model sử dụng connection này để thao tác với database.
Ví dụ kết nối đến database MongoDB local với database name là gettingstarted
// connect to MongoDB mongoose.connect('mongodb://localhost/gettingstarted', { useNewUrlParser: true });
Chúng ta cũng có thể thêm một số parameter như user/pass
mongoose.connect('mongodb://username:password@host:port/database?options...', {useNewUrlParser: true});
Operation Buffering
Mongoose cho phép bạn sử dụng model mà không cần phải đợi đến khi một kết nối giữa mongoose đến MongoDB database được thiết lập.
var MyModel = mongoose.model('Test', new Schema({ name: String })); // Will just hang until mongoose successfully connects MyModel.findOne(function(error, result) { /* ... */ }); setTimeout(function() { mongoose.connect('mongodb://localhost:27017/myapp', {useNewUrlParser: true}); }, 60000);
findOne sẽ chờ cho đến khi kết nối giữa mongoose và MongoDB được thiết lập và bắn câu truy vấn nhận về kết quả. Đó là do mongoose buffers gọi nội bộ lẫn nhau sắp thành hàng chờ cho đến khi mogooose connect thành công.
Để disable cơ chế buffer bạn có thể tắt bufferCommands trong option của của schema.
var schema = new Schema({..}, { bufferCommands: false });
Bạn cũng có thể disable bufferCommands trên toàn bộ các schema
mongoose.set('bufferCommands', false);
Xử lý Error trong connection
Có 2 loại lỗi thường xảy ra với mongoose connection:
- Lỗi khi khởi tạo dữ liệu. Nếu xảy ra lỗi khi thiết lập connection mongoose sẽ không cố gắng để connect lại mà nó sẽ quăng lỗi trong event error và promise mongoose.connect() sẽ bị reject.
- Lỗi sau khi kết nối được thiết lập, mongoose cố gắng kết nối thêm nữa thì nó sẽ quăng lỗi trong event error.
Để xử lý lỗi xảy ra khi thiết lập connect bạn bên sử dụng .catch() hoặc try/catch với async/await.
mongoose.connect('mongodb://localhost:27017/test', { useNewUrlParser: true }). catch(error => handleError(error)); // Or: try { await mongoose.connect('mongodb://localhost:27017/test', { useNewUrlParser: true }); } catch (error) { handleError(error); }
Để xử lý lỗi sau khi connection được thiết lập, chúng ta có thể listen event error của connection.
mongoose.connection.on('error', err => { console.log(err); });
Option trong mongoose connection
Danh sách các option đầy đủ trong MongoDB Node.js cho connect(). Mongoose cũng cung cấp đầy đủ các option trên mà không sửa đổi bất cứ thứ gì. Ngoài ra chúng ta còn có thêm một số option mongoose cung cấp:
- bufferCommands – option của mongoose, để bật tắt cơ chế buffer ở phần trên.
- user/pass – Username và password dùng cho xác thực khi kết nối với MongoDB. Tương đương với auth.user và auth.password.
- autoIndex – Mặc định mongoose sẽ tự động build các indexs được định nghĩa trong schema khi thiết lập kết nối, bạn có thể disable bằng cách set autoIndex false.
- dbname – Tên database khi kết nối, nếu bạn chỉ định dbname nó sẽ override database được chỉ định trên chuỗi connection.
Các option true/false quan trọng trong mongoose:
- useNewUrlParser – connection string hiện tại được MongooDB mark deprecated, trong tương lai có thể không hỗ trợ nữa. Nên bạn cần set useNewUrlParser: true để có thể tiếp tục sử dụng connection string như hiện tại. Note rằng khi bạn chỉ định useNewUrlParser true thì cần chỉ định port trong connection string như mongodb://localhost:27017/dbname.
- useCreateIndex – Mặc định false. Mặc định mongoose sẽ gọi ensureIndex() để xây dựng các index được định nghĩa trong schema. Set thành true mongoose sẽ gọi hàm createIndex() thay vì gọi ensureIndex(). Bạn có thể set global như sau: mongoose.set(‘useCreateIndex’, true). Các bạn nên set useCreateIndex true vì ensureIndex() hiện đã được MongoDB mark deprecation trong tương lai có thể không còn hỗ trợ.
- useFindAndModify – Mặc định true. Set false để findOneAndUpdate() và findOneAndRemove() sử dụng findOneAndUpdate() native thay vì findAndModify().
- autoReconnect: MongoDB driver sẽ tự động kết nối lại với MongoDB. Thông thường chúng ta không nên đụng thằng này trừ khi bạn muốn quản lý các kết nối cho mục đích nào đó. Mặc định autoReconnect là true.
- poolSize – Số lượng socket tối đa mà MongoDB driver sẽ giữ các kết nối. Mặc định là 5.
- bufferMaxEntries – MongoDB driver cũng có cơ chế buffer riêng khi driver mất kết nối. Set option này thành 0 và set bufferCommands false trong schema của bạn nếu bạn nếu bạn muốn các hành động như query false khi driver mất kết nối. Nếu không mặc định nó sẽ chờ đến khi connection được thiết lập lại và tiếp tục các hành động đang chờ.
- connectTimeoutMS – Thời gian MongoDB driver sẽ chờ cho khi khởi tạo kết nối.
- socketTimeoutMS – Thời gian MongoDB driver sẽ chờ cho đến khi kill socket đã được thiết lập kết nối trước đó.
- family – Option này sẽ truyền tham số cho dns.loopup() của Node.js. Nếu bạn không chỉ định mặc định MongoDB driver sẽ tìm IPv6 trước rồi mới đến V4 trong trường hợp V6 tìm không tìm thấy.
const options = { useNewUrlParser: true, useCreateIndex: true, useFindAndModify: false, autoIndex: false, // Don't build indexes reconnectTries: Number.MAX_VALUE, // Never stop trying to reconnect reconnectInterval: 500, // Reconnect every 500ms poolSize: 10, // Maintain up to 10 socket connections // If not connected, return errors immediately rather than waiting for reconnect bufferMaxEntries: 0, connectTimeoutMS: 10000, // Give up initial connection after 10 seconds socketTimeoutMS: 45000, // Close sockets after 45 seconds of inactivity family: 4 // Use IPv4, skip trying IPv6 }; mongoose.connect(uri, options);
Connection Events
Connection trong mongoose thừa kế từ EventEmitter Node.js. Nó sẽ phát những event khi có điều gì xảy ra trong connection như ngắt kết nối, kết nối thành công etc. Dưới đây là danh sách các event của connection:
- connecting – Phát ra khi mongoose bắt đầu khởi tạo một kết nối đến MongoDB driver.
- connected – Phát ra khi mongoose kết nối thành công đến MongoDB driver.
- open – Tương tự connected.
- disconnecting – Phát ra khi bạn bắt đầu gọi Connection#close() để ngắt kết nối đến MongoDB.
- close – Khi ngắt kết nối với MongoDB thành công.
- reconnected – Phát ra nếu mongoose mất kết nối đến MongoDB và kết nối lại thành công.
- error: Khi có lỗi xảy ra trong connection.
- fullsetup: Khi mongoose đang kết nối đến replica set và kết nối thành công đến primary và ít nhất một secondary.
- all: Mongoose kết nối đến các replica set và kết nối thành công đến tất cả các server được chỉ địng trong connection string.
Mongoose keepAlive
KeepAlive đơn giản là khi bạn thiết lập một TCP connection, bạn đặt một khoảng thời gian, bộ đếm giờ sẽ giảm dần từ đó trở về 0 lúc này bạn sẽ gửi một gói tin không chứa data đến endpoint và nếu bạn được phản hồi thì tức là kết nối vẫn còn hoạt động.
Nếu ứng dụng chạy trong một khoảng thời gian dài bạn nên enable keepAlive với một khoảng thời gian cố định. Nếu không đôi lúc bạn sẽ thấy connection closed.
mongoose.connect(uri, { keepAlive: true, keepAliveInitialDelay: 300000 });
Replica Set Connections
Replica set connection là những hosts chạy database MongoDB giống nhau bạn có thể kết nối đến nhiều Replica set và có nhiều bản database backup phòng trường hợp một trong các database server chết sẽ còn các con server khác chạy.
Để connect đến các Replica set
mongoose.connect('mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]' [, options]);
Ví dụ
mongoose.connect('mongodb://user:[email protected]:27017,host2.com:27017,host3.com:27017/testdb');
Để connect duy nhất một replica set
mongoose.connect('mongodb://host1:port1/?replicaSet=rsName');
Multiple connections
Mặc định các model đều sự dụng connection mặc định của mongoose mongoose.connect(). Đôi khi chúng ta cần nhiều kết nối đến mongo, với mỗi kết nối có thể khác nhau về read/write setting, hoặc cũng có thể khác database. Trong trường hợp này chúng ta sẽ sử dụng mongoose.createConnection().
const conn = mongoose.createConnection('mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]', options); const UserModel = conn.model('User', userSchema);
UserModel sẽ được khởi tạo sử dụng bởi conn. Tất cả các hoạt động của UserModel như create, findOne(), update() etc đều diễn ra trên connection conn.