Что такое Mongoose и зачем он нужен?
Mongoose — это Object Data Modeling (ODM) библиотека для MongoDB и Node.js. Она предоставляет мощный, основанный на схемах способ моделирования данных вашего приложения. Если вы работаете с MongoDB в среде Node.js, Mongoose является де-факто стандартом для управления данными.
Зачем он нужен? MongoDB — это NoSQL база данных, которая хранит данные в виде JSON-подобных документов. В отличие от реляционных баз данных, она не требует строгой схемы. Это дает гибкость, но может привести к хаосу в больших проектах. Mongoose решает эту проблему, добавляя слой абстракции, который:
- Определяет схемы (Schemas): Вы описываете структуру ваших документов: какие поля есть, какого они типа, какие значения по умолчанию, обязательны ли они.
- Валидирует данные: Перед сохранением в базу данных Mongoose проверяет, соответствуют ли данные вашей схеме. Это предотвращает запись "мусорных" данных.
- Предоставляет удобные методы: Вместо написания сырых запросов к MongoDB, вы используете интуитивно понятные методы, такие как
.find(),.create(),.updateOne(). - Управляет связями: Вы можете легко связывать документы из разных коллекций (например, пользователя и его заказы) с помощью
populate(). - Middleware (хуки): Позволяет выполнять код до или после определенных операций (например, хешировать пароль перед сохранением).
Простыми словами: Mongoose — это "мостик" между вашим JavaScript-кодом и MongoDB, который делает работу с базой данных структурированной, безопасной и удобной.
Установка Mongoose
Установка Mongoose в ваш Node.js проект выполняется через npm (Node Package Manager). Убедитесь, что у вас установлен Node.js и npm.
Откройте терминал в корне вашего проекта и выполните команду:
npm install mongoose
Эта команда установит последнюю стабильную версию Mongoose и добавит ее в ваш файл package.json в секцию dependencies.
Также вам потребуется установленный и запущенный сервер MongoDB. Вы можете установить его локально или использовать облачный сервис, такой как MongoDB Atlas.
Быстрый старт с примером кода
Давайте создадим простое приложение, которое подключается к MongoDB и сохраняет информацию о пользователе.
- Подключаем Mongoose к базе данных:
// app.js
const mongoose = require('mongoose');
// Строка подключения к MongoDB (замените 'mydatabase' на имя вашей БД)
const mongoURI = 'mongodb://localhost:27017/mydatabase';
mongoose.connect(mongoURI)
.then(() => console.log('Успешно подключено к MongoDB!'))
.catch(err => console.error('Ошибка подключения:', err));
- Определяем схему и модель:
// Определяем схему (Schema) для пользователя
const userSchema = new mongoose.Schema({
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
age: { type: Number, default: 18 }
});
// Создаем модель (Model) на основе схемы
const User = mongoose.model('User', userSchema);
- Создаем и сохраняем документ:
async function createUser() {
try {
// Создаем экземпляр модели
const newUser = new User({
name: 'Иван Иванов',
email: 'ivan@example.com',
age: 30
});
// Сохраняем пользователя в базу данных
const savedUser = await newUser.save();
console.log('Пользователь сохранен:', savedUser);
} catch (error) {
console.error('Ошибка при сохранении:', error.message);
}
}
createUser();
После запуска этого кода, в вашей базе данных MongoDB появится коллекция users с документом, содержащим данные пользователя.
Основные методы и функции Mongoose (8-10 штук)
1. mongoose.connect(uri, options)
Что делает: Устанавливает соединение с MongoDB. Это первый шаг для работы с библиотекой.
Параметры:
uri(String): Строка подключения к MongoDB (например,mongodb://localhost:27017/mydb).options(Object, необязательный): Объект с настройками подключения (например,{ useNewUrlParser: true, useUnifiedTopology: true }).
Пример:
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/testdb', {
useNewUrlParser: true,
useUnifiedTopology: true
})
.then(() => console.log('Подключено'))
.catch(err => console.log('Ошибка:', err));
2. new mongoose.Schema(definition, options)
Что делает: Создает новую схему (Schema). Схема определяет структуру документов в коллекции.
Параметры:
definition(Object): Объект, описывающий поля и их типы (например,{ name: String, age: Number }).options(Object, необязательный): Настройки схемы (например,{ timestamps: true }для автоматического добавления полейcreatedAtиupdatedAt).
Пример:
const bookSchema = new mongoose.Schema({
title: { type: String, required: true },
author: String,
pages: Number,
published: { type: Date, default: Date.now }
}, { timestamps: true });
3. mongoose.model(name, schema)
Что делает: Создает модель (Model) на основе схемы. Модель — это класс, с помощью которого вы создаете и запрашиваете документы из коллекции.
Параметры:
name(String): Имя модели. Mongoose автоматически создаст коллекцию с именем во множественном числе (например,User-> коллекцияusers).schema(Schema): Схема, на основе которой создается модель.
Пример:
const Book = mongoose.model('Book', bookSchema);
// Теперь Book — это модель для работы с коллекцией 'books'
4. Model.create(doc(s))
Что делает: Создает и сохраняет один или несколько документов в базе данных за одну операцию. Это более лаконичная альтернатива new Model() + .save().
Параметры:
doc(s)(Object | Array): Один объект или массив объектов для сохранения.
Пример:
// Создание одного документа
const newBook = await Book.create({ title: 'Война и мир', author: 'Толстой', pages: 1225 });
// Создание нескольких документов
const books = await Book.create([
{ title: '1984', author: 'Оруэлл', pages: 328 },
{ title: 'Мастер и Маргарита', author: 'Булгаков', pages: 480 }
]);
5. Model.find(filter, projection, options)
Что делает: Находит все документы, соответствующие условиям фильтра. Возвращает массив документов.
Параметры:
filter(Object): Условия поиска (например,{ author: 'Толстой' }).projection(Object | String, необязательный): Какие поля включить/исключить (например,{ title: 1, _id: 0 }).options(Object, необязательный): Дополнительные опции (например,{ limit: 10, sort: { pages: -1 } }).
Пример:
// Найти все книги Толстого, показать только названия
const booksByTolstoy = await Book.find(
{ author: 'Толстой' },
{ title: 1, _id: 0 }
);
console.log(booksByTolstoy); // [{ title: 'Война и мир' }, ...]
6. Model.findById(id, projection, options)
Что делает: Находит один документ по его _id. Это самый быстрый способ найти документ по первичному ключу.
Параметры:
id(ObjectId | String): Идентификатор документа.projection(Object | String, необязательный): Какие поля включить/исключить.options(Object, необязательный): Дополнительные опции.
Пример:
const bookId = '60f7b1c5b3f1a72d8c9e1234'; // Пример ID
const book = await Book.findById(bookId);
console.log(book.title); // Выведет название книги
7. Model.findOne(filter, projection, options)
Что делает: Находит первый документ, соответствующий условиям фильтра. Отличается от find() тем, что возвращает один объект, а не массив.
Параметры:
filter(Object): Условия поиска.projection(Object | String, необязательный): Какие поля включить/исключить.options(Object, необязательный): Дополнительные опции.
Пример:
// Найти первую книгу с количеством страниц больше 500
const thickBook = await Book.findOne({ pages: { $gt: 500 } });
console.log(thickBook.title);
8. Model.findByIdAndUpdate(id, update, options)
Что делает: Находит документ по ID и обновляет его. Может вернуть старый или новый документ в зависимости от опции new.
Параметры:
id(ObjectId | String): Идентификатор документа.update(Object): Объект с обновлениями (например,{ $set: { pages: 1300 } }).options(Object, необязательный):{ new: true }— вернуть обновленный документ;{ runValidators: true }— запустить валидацию.
Пример:
const updatedBook = await Book.findByIdAndUpdate(
bookId,
{ $set: { pages: 1300 } },
{ new: true, runValidators: true }
);
console.log(updatedBook.pages); // 1300
9. Model.findByIdAndDelete(id)
Что делает: Находит документ по ID и удаляет его из базы данных. Возвращает удаленный документ.
Параметры:
id(ObjectId | String): Идентификатор документа для удаления.
Пример:
const deletedBook = await Book.findByIdAndDelete(bookId);
if