NodeJS Back-end Инженер

NodeJS Back-end Инженер

Роадмап навыков для прокачки

Document-oriented vs Key-Value — в чём разница в NoSQL?

DatabasesNoSQLdefault

Основная идея

Document-oriented и Key-Value — это два типа NoSQL баз данных с разными моделями хранения данных. Key-Value хранит простые пары "ключ-значение", а Document-oriented хранит структурированные документы (JSON/BSON), которые можно индексировать и искать по полям.

Ключевые аспекты

  • Key-Value — самая простая модель: ключ (строка) → значение (любой blob). Примеры: Redis, Memcached, DynamoDB
  • Document-oriented — ключ → структурированный документ с вложенными полями. Примеры: MongoDB, CouchDB, Firestore
  • Схема — Key-Value не знает о структуре значения, Document DB понимает структуру
  • Запросы — Key-Value только по ключу, Document DB по любым полям документа
  • Индексы — Document DB поддерживает вторичные индексы по полям

Плюсы и минусы

Key-Value:

  • Максимальная производительность чтения/записи
  • Простота масштабирования
  • Ограничены запросы только по ключу

Document-oriented:

  • Гибкие запросы по содержимому
  • Поддержка сложных структур данных
  • Медленнее Key-Value на базовых операциях

Частые ошибки на собеседованиях

  • Путают Document DB с реляционными БД — документы не имеют фиксированной схемы
  • Думают, что Key-Value не может хранить JSON — может, но не понимает его структуру
  • Считают MongoDB "ключ-значение" — MongoDB документо-ориентированная, хотя _id похож на ключ
  • Забывают про гибридные решения — DynamoDB совмещает оба подхода

Введение и проблематика

При выборе NoSQL базы данных одним из ключевых решений является выбор модели данных. Две наиболее популярные модели — Key-Value (ключ-значение) и Document-oriented (документо-ориентированная) — решают разные задачи и имеют различные характеристики производительности.

Какую проблему решают?

Реляционные базы данных требуют фиксированной схемы и плохо масштабируются горизонтально. NoSQL базы данных предлагают альтернативные модели хранения:

  • Key-Value — когда нужна максимальная скорость доступа по уникальному идентификатору
  • Document-oriented — когда нужна гибкость структуры и возможность поиска по содержимому

Базовая теория

Key-Value хранилища

Key-Value — простейшая модель NoSQL. Данные хранятся как пары:

text
ключ (string) → значение (любые данные)

База данных не знает о структуре значения — это просто blob (бинарные данные или строка).

js
// Концептуально Key-Value работает как Map/Dictionary
const keyValueStore = new Map();
 
// Запись
keyValueStore.set("user:123", JSON.stringify({ name: "John", age: 30 }));
keyValueStore.set("session:abc", "encrypted-session-data");
 
// Чтение — только по ключу
const user = keyValueStore.get("user:123");

Примеры Key-Value баз данных:

  • Redis — in-memory, часто используется как кэш
  • Memcached — распределённый кэш
  • Amazon DynamoDB — managed облачный сервис
  • etcd — хранение конфигураций в Kubernetes

Document-oriented хранилища

Document-oriented базы хранят структурированные документы (обычно JSON или BSON):

text
ключ (_id) → документ (JSON с вложенной структурой)

База данных понимает структуру документа и может индексировать отдельные поля.

js
// Документ в MongoDB
{
  "_id": ObjectId("507f1f77bcf86cd799439011"),
  "name": "John",
  "age": 30,
  "address": {
    "city": "Moscow",
    "street": "Tverskaya"
  },
  "orders": [
    { "id": 1, "total": 1500 },
    { "id": 2, "total": 3200 }
  ]
}

Примеры Document-oriented баз данных:

  • MongoDB — самая популярная документная БД
  • CouchDB — HTTP API, встроенная репликация
  • Firebase Firestore — realtime облачная БД
  • Amazon DocumentDB — managed MongoDB-совместимый сервис

Практические примеры

Операции с Key-Value (Redis)

js
import Redis from 'ioredis';
const redis = new Redis();
 
// Запись
await redis.set('user:123', JSON.stringify({ name: 'John', age: 30 }));
 
// Чтение по ключу
const userData = await redis.get('user:123');
const user = JSON.parse(userData);
 
// TTL (время жизни) — отличительная фича Key-Value
await redis.setex('session:abc', 3600, 'session-data'); // истечёт через 1 час
 
// ❌ Нельзя искать по содержимому
// redis.find({ name: 'John' }) — такого НЕТ!

Операции с Document DB (MongoDB)

js
import { MongoClient } from 'mongodb';
const client = new MongoClient('mongodb://localhost:27017');
const db = client.db('myapp');
const users = db.collection('users');
 
// Запись документа
await users.insertOne({
  name: 'John',
  age: 30,
  address: { city: 'Moscow' }
});
 
// Чтение по _id
const user = await users.findOne({ _id: new ObjectId('507f1f77bcf86cd799439011') });
 
// ✅ Поиск по любому полю
const moscowUsers = await users.find({ 'address.city': 'Moscow' }).toArray();
 
// ✅ Сложные запросы
const adults = await users.find({
  age: { $gte: 18 },
  'address.city': { $in: ['Moscow', 'SPb'] }
}).toArray();

Сравнение моделей

Характеристики Key-Value:

  • Модель: ключ → blob
  • Запросы: только по ключу (GET/SET/DELETE)
  • Схема: отсутствует, значение — чёрный ящик
  • Индексы: нет (только первичный ключ)
  • Производительность: O(1) для всех операций
  • Масштабирование: легко шардируется по ключу

Когда использовать:

  • Кэширование
  • Сессии пользователей
  • Очереди сообщений
  • Счётчики и rate limiting
  • Хранение конфигураций

Пограничные кейсы

⚠️

Key-Value может хранить JSON, но не понимает его структуру. Если вам нужен поиск по полям — используйте Document DB или добавьте вторичные индексы вручную (как в Redis с Sorted Sets).

Гибридные решения

Некоторые базы данных совмещают оба подхода:

DynamoDB — Key-Value с поддержкой вложенных атрибутов:

js
// Можно запрашивать по атрибутам, но менее гибко чем MongoDB
const params = {
  TableName: 'Users',
  Key: { userId: '123' },  // Обязательный ключ
  ProjectionExpression: 'name, address.city'  // Проекция полей
};

Redis с JSON модулем — добавляет возможность работы с JSON:

bash
# RedisJSON модуль
JSON.SET user:123 $ '{"name":"John","age":30}'
JSON.GET user:123 $.name  # Получить конкретное поле

Плюсы и минусы

АспектKey-ValueDocument-oriented
Скорость✅ Максимальная⚠️ Зависит от запроса
Гибкость запросов❌ Только по ключу✅ По любым полям
Сложность✅ Простая⚠️ Больше настроек
Масштабирование✅ Тривиальное⚠️ Требует планирования
Транзакции❌ Ограничены⚠️ Частичная поддержка
Индексы❌ Нет✅ Вторичные индексы

Вопросы интервьюера

Q: Можно ли использовать MongoDB как Key-Value хранилище?

Да, если всегда запрашивать по _id. Но это неэффективно — Redis будет быстрее для такого use case.

Q: Почему Redis используют как кэш, а не MongoDB?

Redis хранит данные в памяти (in-memory) и оптимизирован для простых операций GET/SET. MongoDB работает с диском и оптимизирована для сложных запросов.

Q: Что такое BSON в MongoDB?

Binary JSON — бинарный формат хранения документов. Добавляет типы (Date, ObjectId, Binary) и эффективнее для хранения/передачи.

Q: Когда Key-Value лучше Document DB?

Когда не нужен поиск по содержимому: кэши, сессии, очереди. Key-Value проще масштабировать и быстрее на базовых операциях.


Источники