Статьи

MongoDB Драйвер Советы и хитрости: Mongoose

Многие из запросов на поддержку, которые мы получаем в MongoLab, представляют собой вопросы о том, как правильно настроить и использовать определенные драйверы MongoDB и клиентские библиотеки.

Этот пост является вторым в серии, где мы подробно рассмотрим популярные драйверы MongoDB (в прошлый раз мы рассмотрели Mongoid ). Драйвер, который мы рассмотрим сегодня, — Mongoose , поддерживаемый Аароном Хекманном (@aaronheckmann) и официально поддерживаемый MongoDB, Inc.

В этом посте:

Мангуста

Mongoose — это объектный документ Node.js (ODM). Для реляционных людей ODM являются эквивалентом MongoDB Object Relational Mappers (ORM). Одна из основных причин, по которой разработчики используют ODM, такие как Mongoose, заключается в том, что он дает им возможность определять схему для своих документов, которую затем можно использовать для сопоставления документов с объектами на их языке программирования. В Mongoose эта функция служит простым переходом для бывших разработчиков Ruby on Rails, привыкших работать с ActiveRecord.

Mongoose написан поверх собственного драйвера MongoDB для Node.js, который также официально поддерживается MongoDB, Inc. Хотя Mongoose определяет модели и использует их для запросов, нативный MongoDB для Node.js предоставляет более традиционный интерфейс запросов. Мы расскажем об этом родном драйвере в следующей части этой серии блогов.

Этот пост призван помочь вам понять, как эффективно настроить и использовать Mongoose в вашем приложении MongoDB.

Простой пример мангуста

Вы можете найти простой пример подключения, вставки, обновления и запросов с помощью Mongoose в Языковом центре MongoLab .

Готовые к настройке соединения

Мы часто видим, что у пользователей возникают проблемы с подключением к MongoLab с помощью драйвера Mongoose. Основной причиной является почти всегда неправильная конфигурация драйвера, особенно из-за тайм-аутов. Ниже приведен пример подключения с использованием параметров драйвера, рекомендуемых MongoLab:

// mongoose 3.8.x
var mongoose = require('mongoose');
// mongodb-uri 0.9.x
var uriUtil = require('mongodb-uri');
 
/* 
 * Mongoose by default sets the auto_reconnect option to true.
 * We recommend setting socket options at both the server and replica set level.
 * We recommend a 30 second connection timeout because it allows for 
 * plenty of time in most operating environments.
 */
var options = { server: { socketOptions: { keepAlive: 1, connectTimeoutMS: 30000 } }, 
                replset: { socketOptions: { keepAlive: 1, connectTimeoutMS : 30000 } } };       
 
/*
 * Mongoose uses a different connection string format than MongoDB's standard.
 * Use the mongodb-uri library to help you convert from the standard format to
 * Mongoose's format.
 */
var mongodbUri = 'mongodb://user:pass@host:port/db';
var mongooseUri = uriUtil.formatMongoose(mongodbUri);
 
mongoose.connect(mongooseUri, options);
var conn = mongoose.connection;             
 
conn.on('error', console.error.bind(console, 'connection error:'));  
 
conn.once('open', function() {
  // Wait for the database connection to establish, then start the app.                         
});

...

Дополнительные параметры подключения, которые поддерживаются основным драйвером Node.js, можно найти здесь .

Мангуста советы и хитрости

Mongoose требует другого формата строки подключения

Формат URI Mongoose следует соглашению:

mongodb: // пользователь: pass @ host1: port1 / database, mongodb: // пользователь: pass @ host2: port2, mongodb: // пользователь: pass @ host3: port3

Обратите внимание, что имя базы данных включено в первый узел. Также обратите внимание, что для каждого узла требуется префикс «mongodb: //».

Этот формат отличается от стандартного формата строки подключения MongoDB, который выглядит следующим образом:

MongoDB: // пользователь: пароль @ host1: port1, host2: port2, host3: port3 / база данных

В простом примере Mongoose, на который мы ссылались выше, мы используем функцию из пакета mongodb-uri для преобразования стандартного формата строки подключения MongoDB в тот, который ожидает Mongoose.

Увеличьте время ожидания соединения, чтобы уменьшить количество ошибок

Распространенная ошибка, которую мы видим с драйвером Mongoose, — ошибка подключения Mongo. Например:

Ошибка подключения Mongo: Ошибка: первичный не найден в наборе

Эта ошибка выдается, когда у Mongoose возникают трудности с установлением соединения. В зависимости от типа соединения, создаваемого драйвером (сервер или набор реплик), значение тайм-аута по умолчанию варьируется от 1 до 5 секунд. Мы часто видим, что пользователи, которые запускают свое приложение с платформой как услуга (PaaS), такой как Heroku, обнаружат, что их драйверу требуется больше времени для установления соединения с базой данных, особенно когда динамометры только запускаются. По этой причине мы рекомендуем подождать до 30 секунд для установления соединения.

Новые соединения требуют блокировки записи; будьте осторожны с индексными сборками

Чтобы установить соединение с MongoDB, драйвер должен сначала подключиться и пройти аутентификацию на всех узлах набора реплик. Шаг аутентификации требует блокировки записи для завершения.

Начиная с MongoDB 2.4.x, построение индекса на вторичных серверах выполняется на переднем плане и удерживает блокировку записи. В результате любое соединение, пытающееся пройти проверку подлинности (для которого требуется блокировка записи), должно ждать завершения построения индекса. Чтобы избежать непредвиденных ошибок, мы рекомендуем создавать индексы в периоды непиковой нагрузки, когда приложение может повторно использовать существующие подключения, которые уже прошли проверку подлинности.

Это поведение немного отличается от других драйверов, которые обычно могут обрабатывать невозможность аутентификации для вторичных серверов в кластере наборов реплик.

Правильно настроить обработку ошибок приложения

Обработка ошибок Node.js часто бывает сложной. Для новых разработчиков важно помнить, что большинство ошибок возвращаются через обратные вызовы. Вы можете обрабатывать ошибки в обратном вызове, или вы можете рассмотреть возможность передачи их в централизованную инфраструктуру, используя соглашение « следующего » обратного вызова Node.js, предлагаемое для каждого маршрута Express .

app.get('/docs', function (req, res, next) {
  Model.find({}, function (err, docs) {
    if (err) return next(err);
  })
})

Однако некоторые ошибки происходят вне контекста отдельной операции базы данных. Эти ошибки, например, ошибки соединения, требуют, чтобы обработчики были зарегистрированы в более широкой области (само соединение).

var conn = mongoose.createConnection(..); 
conn.on('error', handler);

Аарон Хекманн, основной сопровождающий проекта Mongoose, дает несколько полезных советов по обработке ошибок Mongoose и Express в этом потоке StackOverflow .

Вы все готово!

Мы надеемся, что этот пост поможет пролить свет на некоторые вещи, уникальные для Mongoose. Если у вас есть какие-либо советы и рекомендации, которыми вы хотели бы поделиться, пожалуйста, оставьте их в комментариях или напишите нам по адресу [email protected], чтобы мы могли поделиться своими знаниями. Счастливого взлома!