Подключение MongoDB
Внимание
Данная статья документации написана нейросетью. Возможны некоторые расхождения и неточность информации!
Руководство по подключению к MongoDB в IO7 фреймворке.
Требования
Для работы с MongoDB необходим PHP расширение mongodb:
pecl install mongodb
Или через apt:
apt-get install php-mongodb
MongoManager
Пространство имён: IO\Database
Менеджер MongoDB с ленивой загрузкой соединений. Реализован как синглтон.
Статические методы
getInstance()
public static function getInstance(): self
Получить синглтон-экземпляр менеджера.
$manager = MongoManager::getInstance();
Методы конфигурации
addConfig()
public function addConfig(
string $uri,
string $database,
string $name = 'default',
array $options = []
): self
Добавить конфигурацию подключения (ленивая загрузка — подключение устанавливается при первом обращении).
| Параметр | Тип | Значение по умолчанию | Обязателен | Описание |
|---|---|---|---|---|
$uri | string | — | Да | MongoDB URI подключения |
$database | string | — | Да | Имя базы данных |
$name | string | 'default' | Нет | Имя подключения |
$options | array | [] | Нет | Дополнительные опции подключения |
$manager = MongoManager::getInstance();
$manager
->addConfig('mongodb://localhost:27017', 'mydb', 'main')
->addConfig('mongodb://replica1:27017,replica2:27017', 'logs', 'logs', [
'replicaSet' => 'rs0',
]);
Методы подключения
isAvailable()
public function isAvailable(?string $name = null): bool
Проверить доступность подключения.
if (MongoManager::getInstance()->isAvailable()) {
// MongoDB доступен
}
getClient()
public function getClient(?string $name = null): \MongoDB\Client
Получить клиент MongoDB.
| Параметр | Тип | Значение по умолчанию | Обязателен | Описание |
|---|---|---|---|---|
$name | ?\string | null | Нет | Имя подключения (null — default) |
getDatabase()
public function getDatabase(?string $name = null): \MongoDB\Database
Получить объект базы данных.
getCollection()
public function getCollection(
string $collection,
?string $connection = null
): \MongoDB\Collection
Получить объект коллекции.
| Параметр | Тип | Значение по умолчанию | Обязателен | Описание |
|---|---|---|---|---|
$collection | string | — | Да | Имя коллекции |
$connection | ?\string | null | Нет | Имя подключения |
$users = MongoManager::getInstance()->getCollection('users');
$logs = MongoManager::getInstance()->getCollection('logs', 'logs');
CRUD операции
find()
public function find(
string $collection,
array $filter = [],
array $options = [],
?string $connection = null
): array
Поиск документов.
| Параметр | Тип | Значение по умолчанию | Обязателен | Описание |
|---|---|---|---|---|
$collection | string | — | Да | Имя коллекции |
$filter | array | [] | Нет | Критерии фильтрации |
$options | array | [] | Нет | Опции запроса |
$connection | ?\string | null | Нет | Имя подключения |
$activeUsers = MongoManager::getInstance()->find('users', [
'active' => true,
], [
'limit' => 10,
'sort' => ['created_at' => -1],
]);
findOne()
public function findOne(
string $collection,
array $filter = [],
array $options = [],
?string $connection = null
): ?array
Найти один документ.
$user = MongoManager::getInstance()->findOne('users', [
'_id' => new \MongoDB\BSON\ObjectId('...'),
]);
if ($user) {
echo $user['name'];
}
insert()
public function insert(
string $collection,
array $document,
?string $connection = null
): \MongoDB\InsertOneResult
Вставить один документ.
$result = MongoManager::getInstance()->insert('users', [
'name' => 'Иван',
'email' => 'ivan@example.com',
'active' => true,
]);
$newId = $result->getInsertedId();
insertMany()
public function insertMany(
string $collection,
array $documents,
?string $connection = null
): \MongoDB\InsertManyResult
Вставить несколько документов.
$result = MongoManager::getInstance()->insertMany('logs', [
['msg' => 'Событие 1', 'level' => 'info'],
['msg' => 'Событие 2', 'level' => 'error'],
['msg' => 'Событие 3', 'level' => 'warning'],
]);
echo "Вставлено: {$result->getInsertedCount()}";
update()
public function update(
string $collection,
array $filter,
array $update,
array $options = [],
?string $connection = null
): \MongoDB\UpdateResult
Обновить один документ.
$result = MongoManager::getInstance()->update('users', [
'_id' => new \MongoDB\BSON\ObjectId('...'),
], [
'$set' => ['active' => false],
]);
updateMany()
public function updateMany(
string $collection,
array $filter,
array $update,
array $options = [],
?string $connection = null
): \MongoDB\UpdateResult
Обновить несколько документов.
$result = MongoManager::getInstance()->updateMany('logs', [
'created_at' => ['$lt' => new \MongoDB\BSON\UTCDateTime('-30 days')],
], [
'$set' => ['archived' => true],
]);
delete()
public function delete(
string $collection,
array $filter,
array $options = [],
?string $connection = null
): \MongoDB\DeleteResult
Удалить один документ.
deleteMany()
public function deleteMany(
string $collection,
array $filter,
array $options = [],
?string $connection = null
): \MongoDB\DeleteResult
Удалить несколько документов.
$result = MongoManager::getInstance()->deleteMany('temp_data', [
'expires_at' => ['$lt' => new \MongoDB\BSON\UTCDateTime()],
]);
Агрегация
aggregate()
public function aggregate(
string $collection,
array $pipeline,
?string $connection = null
): array
Выполнить агрегационный pipeline.
| Параметр | Тип | Значение по умолчанию | Обязателен | Описание |
|---|---|---|---|---|
$collection | string | — | Да | Имя коллекции |
$pipeline | array | — | Да | Агрегационный pipeline |
$connection | ?\string | null | Нет | Имя подключения |
// Подсчёт по статусу
$results = MongoManager::getInstance()->aggregate('orders', [
['$group' => [
'_id' => '$status',
'count' => ['$sum' => 1],
'total' => ['$sum' => '$amount'],
]],
['$sort' => ['count' => -1]],
]);
Транзакции
startSession()
public function startSession(): \MongoDB\ClientSession
Начать сессию (для транзакций).
transaction()
public function transaction(callable $callback, ?string $connection = null)
Выполнить транзакцию.
$result = MongoManager::getInstance()->transaction(function (\MongoDB\ClientSession $session): bool {
// Все операции в рамках транзакции
$session->getDatabase()->selectCollection('accounts')->updateOne(
['_id' => 'user1'],
['$inc' => ['balance' => -100]],
['session' => $session]
);
$session->getDatabase()->selectCollection('accounts')->updateOne(
['_id' => 'user2'],
['$inc' => ['balance' => 100]],
['session' => $session]
);
return true;
});
Безопасное выполнение
whenAvailable()
public function whenAvailable(
callable $callback,
$default = null,
?string $connection = null
)
Выполнить функцию только если MongoDB доступен.
$user = MongoManager::getInstance()->whenAvailable(function(MongoManager $manager): ?array {
return $manager->findOne('users', ['_id' => $id]);
}, null);
if ($user === null) {
// MongoDB недоступен или пользователь не найден
}
Примеры
Полная инициализация
use IO\Database\MongoManager;
$mongo = MongoManager::getInstance();
$mongo
->addConfig('mongodb://localhost:27017', 'myapp', 'main')
->addConfig('mongodb://localhost:27017', 'myapp_logs', 'logs');
// Проверка доступности
if ($mongo->isAvailable()) {
echo "MongoDB подключён\n";
}
Работа с документами
$users = MongoManager::getInstance()->getCollection('users');
// Вставка
$result = $users->insertOne([
'name' => 'Иван',
'email' => 'ivan@example.com',
'tags' => ['admin', 'vip'],
'meta' => [
'created_ip' => '192.168.1.1',
'browser' => 'Chrome',
],
]);
// Поиск
$user = $users->findOne(['_id' => $result->getInsertedId()]);
// Обновление
$users->updateOne(
['_id' => $result->getInsertedId()],
['$push' => ['tags' => 'premium']]
);
// Удаление
$users->deleteOne(['_id' => $result->getInsertedId()]);
Агрегация
// Статистика по пользователям
$stats = MongoManager::getInstance()->aggregate('orders', [
// Группировка по статусу
['$group' => [
'_id' => '$status',
'count' => ['$sum' => 1],
'total_amount' => ['$sum' => '$amount'],
'avg_amount' => ['$avg' => '$amount'],
]],
// Сортировка по количеству
['$sort' => ['count' => -1]],
// Лимит
['$limit' => 10],
]);
foreach ($stats as $stat) {
echo "Статус: {$stat['_id']}\n";
echo " Количество: {$stat['count']}\n";
echo " Сумма: {$stat['total_amount']}\n";
}
Транзакция
$result = MongoManager::getInstance()->transaction(function (\MongoDB\ClientSession $session): bool {
$db = $session->getDatabase('myapp');
// Списание
$db->selectCollection('accounts')->updateOne(
['_id' => 'user1'],
['$inc' => ['balance' => -500]],
['session' => $session]
);
// Зачисление
$db->selectCollection('accounts')->updateOne(
['_id' => 'user2'],
['$inc' => ['balance' => 500]],
['session' => $session]
);
// Логирование
$db->selectCollection('transfers')->insertOne([
'from' => 'user1',
'to' => 'user2',
'amount' => 500,
], ['session' => $session]);
return true;
});
Рекомендации
- Используйте
whenAvailable()для отказоустойчивости — MongoDB не должен блокировать приложение - Настройте replica set для продакшен-окружения
- Используйте индексы для ускорения запросов
- Избегайте
$unset— используйте$setс null - Используйте транзакции для критических операций
- Разделяйте коллекции для данных и логов
FAQ
Что делать, если MongoDB недоступен?
$mongo = MongoManager::getInstance();
if ($mongo->isAvailable()) {
$data = $mongo->find('logs', ['level' => 'error']);
} else {
// Fallback: читаем из файлов или другой БД
$data = [];
}
Как подключиться к Replica Set?
$mongo->addConfig(
'mongodb://replica1:27017,replica2:27017,replica3:27017',
'mydb',
'main',
['replicaSet' => 'rs0']
);
Как работает ленивая загрузка?
Подключение устанавливается только при первом обращении к getDatabase(), getCollection(), find() и т.д. Конфигурация через addConfig() не создает соединения.
Как использовать GridFS?
$bucket = MongoManager::getInstance()->getDatabase()->selectGridFSBucket();
// Загрузка
$bucket->uploadFromStream('file.txt', fopen('/path/to/file.txt', 'r'));
// Скачивание
$download = $bucket->openDownloadStreamByName('file.txt');
stream_copy_to_stream($download, fopen('/tmp/downloaded.txt', 'w'));
Как создать индексы?
$collection = MongoManager::getInstance()->getCollection('users');
$collection->createIndex(['email' => 1], ['unique' => true]);
$collection->createIndex(['status' => 1, 'created_at' => -1]);