Схема, валидация и антипаттерны

Почему «бессхемная» БД всё равно нуждается в схеме и как заставить базу её проверять.

MongoDB не навязывает схему, но схема всё равно есть — в коде приложения; база умеет проверять её через валидацию JSON Schema.

«Бессхемная» — это про гибкость, а не про хаос

Отсутствие принудительной схемы не значит, что структуру можно не продумывать. Приложение всё равно ожидает у пользователя поле email, а у заказа — items. Просто следить за этим теперь должны вы, а не CREATE TABLE. Гибкость удобна для эволюции (добавить поле — не миграция), но требует дисциплины.

Валидация схемы средствами базы

Чтобы база отвергала «битые» документы, на коллекцию вешают валидатор по стандарту JSON Schema. Опишем правила для users: обязательны name и email, возраст — целое число не меньше 0:

db.createCollection("users", {
  validator: {
    $jsonSchema: {
      bsonType: "object",
      required: ["name", "email"],
      properties: {
        name:  { bsonType: "string" },
        email: { bsonType: "string" },
        age:   { bsonType: "int", minimum: 0 }
      }
    }
  }
})

Теперь вставка документа без email или с отрицательным возрастом будет отклонена. Валидацию можно добавить и к существующей коллекции через collMod. Это страховка от ошибок приложения — но не замена продуманной модели данных.

Антипаттерн 1: безграничные массивы

Встраивать массив, который растёт без предела (все события пользователя, все сообщения чата), — ошибка. Документ имеет лимит 16 МБ, а большие массивы замедляют любые операции с документом. Такие данные выносят в отдельную коллекцию со ссылкой.

Антипаттерн 2: огромные документы и лишние поля

Не складывайте в документ всё подряд «про запас». Чем больше документ, тем дороже его читать и писать целиком. Храните то, что нужно реальным запросам.

Антипаттерн 3: мыслить таблицами

Самая частая ошибка переходящих с SQL — слепо переносить нормализованную схему: коллекция на каждую таблицу и $lookup вместо каждого JOIN. Документная модель раскрывается, когда вы проектируете под запросы и используете встраивание там, где оно уместно. Не «как было в SQL», а «как это читается».

Итог

  • Схема в MongoDB существует — в приложении; база может её проверять через $jsonSchema-валидацию.
  • Валидатор задают при createCollection (или добавляют через collMod) — страховка от битых документов.
  • Антипаттерны: безграничные встроенные массивы, раздутые документы и «мышление таблицами».
Проверьте себя
1. Верно ли, что «бессхемная» MongoDB освобождает от продумывания структуры данных?
AДа, структуру можно не планировать
BНет, схема всё равно нужна — за ней следит приложение, а база умеет её проверять
CДа, база сама придумает оптимальную схему
DНет, схему обязательно задавать через CREATE TABLE
2. Чем задаётся валидация структуры документов в MongoDB?
AКомандой CREATE SCHEMA
BПравилами $jsonSchema в валидаторе коллекции
CОтдельной базой данных
DПолем _id
3. Какой из вариантов — антипаттерн при моделировании в MongoDB?
AВстраивать небольшой ограниченный массив
BВыносить безгранично растущий массив в отдельную коллекцию
CВстраивать массив, который может расти неограниченно, прямо в документ
DПроектировать структуру под частые запросы
Поддержать проект