> Для чего используется MongoDB (Go)

Уровень: senior · Роль: backend · Язык: Go · Категория: Технические вопросы

Компании: Kalabi

Стек: Go

> Пример ответа

Короткий ответ

MongoDB - документоориентированная NoSQL база данных, используемая для хранения гибких JSON-подобных документов. Основные сценарии: быстрая разработка с изменяемой схемой, high-load приложения с горизонтальным масштабированием через sharding, хранение телеметрии, логов, каталогов товаров. В Go-бэкенде часто применяется как основное хранилище для сервисов с нереляционной моделью данных или как вспомогательное - для кэшей, очередей (Change Streams), аналитических агрегаций.

Подробное объяснение

MongoDB хранит данные в BSON-документах, сгруппированных в коллекции. Ключевые особенности:

  • Схема-less модель - документы в одной коллекции могут иметь разный набор полей, что упрощает эволюцию модели данных без миграций.
  • Горизонтальное масштабирование - автоматический sharding по shard key, в отличие от вертикального масштабирования реляционных БД.
  • Встроенные документы и массивы - позволяют моделировать вложенные структуры без JOIN, что снижает количество запросов.
  • Агрегационный pipeline - мощный инструмент для трансформации и анализа данных на стороне БД.
  • Change Streams - подписка на изменения коллекций, удобно для event-driven архитектур.
  • TTL-индексы - автоматическое удаление устаревших документов, полезно для логов и сессий.

Trade-off: отсутствие транзакций в классическом понимании (поддержка multi-document transactions появилась с версии 4.0, но с ограничениями), eventual consistency в распределённой конфигурации, неэффективность для сложных JOIN-запросов и строгих связей между сущностями.

В Go-стеке MongoDB используется через официальный драйвер mongo-go-driver, который поддерживает контексты, пулы соединений, bulk-операции и aggregation pipeline.

На практике

Для Go-бэкенда MongoDB выбирают, когда:

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

Не стоит использовать MongoDB для финансовых систем с жёсткими требованиями к ACID, для доменов с большим количеством связей many-to-many, где реляционная модель естественнее.

При проектировании важно продумать shard key заранее - от этого зависит равномерность распределения данных и производительность. Также нужно настраивать индексы под паттерны запросов, иначе aggregation pipeline будет работать медленно.

Пример кода

GO
package main
import (
"context"
"fmt"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
type User struct {
Name string `bson:"name"`
Email string `bson:"email"`
Tags []string `bson:"tags,omitempty"`
}
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
client, err := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://localhost:27017"))
if err != nil {
panic(err)
}
defer client.Disconnect(ctx)
coll := client.Database("app").Collection("users")
// вставка
_, err = coll.InsertOne(ctx, User{Name: "Alice", Email: "alice@example.com", Tags: []string{"go", "backend"}})
if err != nil {
panic(err)
}
// поиск с фильтром
var result User
err = coll.FindOne(ctx, bson.M{"email": "alice@example.com"}).Decode(&result)
if err != nil {
panic(err)
}
fmt.Printf("found: %+v\n", result)
// агрегация: подсчёт пользователей по тегам
pipeline := mongo.Pipeline{
{{Key: "$unwind", Value: "$tags"}},
{{Key: "$group", Value: bson.D{
{Key: "_id", Value: "$tags"},
{Key: "count", Value: bson.D{{Key: "$sum", Value: 1}}},
}}},
{{Key: "$sort", Value: bson.D{{Key: "count", Value: -1}}}},
}
cursor, err := coll.Aggregate(ctx, pipeline)
if err != nil {
panic(err)
}
defer cursor.Close(ctx)
for cursor.Next(ctx) {
var doc bson.M
cursor.Decode(&doc)
fmt.Printf("tag %v: %v\n", doc["_id"], doc["count"])
}
}

Как отвечать на собеседовании

Начните с назначения - хранение гибких документов с горизонтальным масштабированием. Затем перечислите ключевые сценарии: изменяемая схема, вложенные структуры, high-load запись, телеметрия. Обязательно упомяните trade-off: отсутствие полноценных JOIN, особенности транзакций, необходимость проектирования shard key.

Покажите понимание отличий от реляционных БД: документная модель против табличной, встроенные документы против JOIN, eventual consistency против strong consistency. Приведите пример из практики: почему выбрали MongoDB для конкретной задачи и с какими проблемами столкнулись.

Если спрашивают про Go - упомяните mongo-go-driver, работу с контекстами, bulk-операции, Change Streams. Подчеркните, что aggregation pipeline переносит часть логики на сторону БД, разгружая приложение.

Что проверяет интервьюер

  • понимание разницы между SQL и NoSQL, осознанный выбор MongoDB;
  • знание модели данных: документы, коллекции, вложенные структуры;
  • понимание масштабирования: sharding, replica sets, trade-off консистентности;
  • практический опыт: индексы, агрегации, типичные ошибки проектирования;
  • способность объяснить, когда MongoDB - плохой выбор.

Типичные ошибки

  • утверждение, что MongoDB "быстрее" SQL - без контекста это неверно;
  • игнорирование shard key при проектировании - приводит к дисбалансу данных;
  • использование MongoDB для данных с жёсткими связями и транзакциями;
  • отсутствие индексов под реальные запросы - деградация производительности;
  • непонимание, что $lookup - это аналог LEFT JOIN, но с ограничениями по производительности;
  • забывают про TTL-индексы и Change Streams как полезные фичи для типовых задач.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью