← Назад к вопросам

Сталкивался ли с нереляционными базами данных

1.2 Junior🔥 91 комментариев
#Soft Skills и карьера

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Работа с нереляционными базами данных

Да, я имею практический опыт работы с NoSQL базами данных. Они стали неотъемлемой частью современной разработки, особенно в системах с высокими требованиями к масштабируемости и производительности.

Типы NoSQL БД

В своей работе я сталкивался с основными категориями:

1. MongoDB (Document Store)

Московский документ-ориентированная БД с гибкой схемой:

// Пример с Java Driver
public class MongoUserRepository {
    private final MongoCollection<Document> collection;
    
    public void saveUser(User user) {
        Document doc = new Document()
            .append("_id", user.getId())
            .append("name", user.getName())
            .append("email", user.getEmail())
            .append("createdAt", new Date());
        
        collection.insertOne(doc);
    }
    
    public User findByEmail(String email) {
        Document doc = collection.find(new Document("email", email))
            .first();
        
        if (doc == null) return null;
        
        return new User(
            doc.getObjectId("_id"),
            doc.getString("name"),
            doc.getString("email")
        );
    }
    
    public void updateUser(String id, User user) {
        Document update = new Document("$set", new Document()
            .append("name", user.getName())
            .append("updatedAt", new Date()));
        
        collection.updateOne(
            new Document("_id", new ObjectId(id)),
            update
        );
    }
}

2. Redis (Key-Value Store)

Высокопроизводительное хранилище ключ-значение с поддержкой различных структур:

// Пример с Jedis
public class RedisCacheService {
    private final Jedis jedis;
    
    // Кеширование сессий
    public void setSession(String userId, String sessionData, int ttlSeconds) {
        jedis.setex("session:" + userId, ttlSeconds, sessionData);
    }
    
    public String getSession(String userId) {
        return jedis.get("session:" + userId);
    }
    
    // Счётчики
    public void incrementPageViews(String pageId) {
        jedis.incr("views:" + pageId);
    }
    
    // Leaderboard (сортированное множество)
    public void updateScore(String userId, long score) {
        jedis.zadd("leaderboard", (double) score, userId);
    }
    
    public List<String> getTopPlayers(int limit) {
        return jedis.zrevrange("leaderboard", 0, limit - 1);
    }
    
    // Очередь (List)
    public void pushTask(String task) {
        jedis.rpush("tasks:queue", task);
    }
    
    public String popTask() {
        return jedis.lpop("tasks:queue");
    }
}

3. Elasticsearch (Search Engine)

Оптимизирован для полнотекстового поиска и аналитики:

// Пример с Elasticsearch Java Client
public class ElasticsearchProductService {
    private final ElasticsearchClient client;
    
    public void indexProduct(Product product) throws IOException {
        IndexRequest<Product> request = IndexRequest.of(i -> i
            .index("products")
            .id(product.getId())
            .document(product));
        
        client.index(request);
    }
    
    public List<Product> searchByName(String query) throws IOException {
        SearchRequest request = SearchRequest.of(s -> s
            .index("products")
            .query(q -> q
                .match(m -> m
                    .field("name")
                    .query(query))));
        
        SearchResponse<Product> response = client.search(request, Product.class);
        
        return response.hits().hits().stream()
            .map(HitMetadata::source)
            .collect(Collectors.toList());
    }
    
    public List<Product> advancedSearch(String name, double minPrice, double maxPrice) throws IOException {
        SearchRequest request = SearchRequest.of(s -> s
            .index("products")
            .query(q -> q
                .bool(b -> b
                    .must(m -> m.match(mm -> mm.field("name").query(name)))
                    .filter(f -> f.range(r -> r.field("price").gte(json(minPrice))))
                    .filter(f -> f.range(r -> r.field("price").lte(json(maxPrice)))))));
        
        SearchResponse<Product> response = client.search(request, Product.class);
        return response.hits().hits().stream()
            .map(HitMetadata::source)
            .collect(Collectors.toList());
    }
}

4. Cassandra (Columnar Database)

Распределённая БД, оптимизирована для записи большого объёма данных:

// Пример с DataStax Driver
public class CassandraMetricsRepository {
    private final CqlSession session;
    
    public void recordMetric(String serverId, long timestamp, double value) {
        PreparedStatement pst = session.prepare(
            "INSERT INTO metrics (server_id, timestamp, value) VALUES (?, ?, ?)")
        ;
        
        session.execute(pst.bind(serverId, Instant.ofEpochMilli(timestamp), value));
    }
    
    public List<Double> getMetricsForServer(String serverId, long startTime, long endTime) {
        ResultSet rs = session.execute(
            "SELECT value FROM metrics " +
            "WHERE server_id = ? " +
            "AND timestamp >= ? " +
            "AND timestamp <= ? " +
            "ORDER BY timestamp DESC",
            serverId, Instant.ofEpochMilli(startTime), Instant.ofEpochMilli(endTime)
        );
        
        return rs.all().stream()
            .map(row -> row.getDouble("value"))
            .collect(Collectors.toList());
    }
}

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

MongoDB — когда нужна гибкая схема и вложенные структуры Redis — для кеша, сессий, счётчиков и реал-тайм данных Elasticsearch — для поиска и аналитики Cassandra — для распределённых систем с высокой нагрузкой на запись

Реальные примеры из практики

Система кеширования с Redis

public class UserService {
    private final UserRepository db;
    private final RedisCacheService cache;
    
    public User getUser(String userId) {
        // Сначала ищем в кеше
        String cachedUser = cache.get("user:" + userId);
        if (cachedUser != null) {
            return deserializeUser(cachedUser);
        }
        
        // Если нет, ищем в БД
        User user = db.findById(userId);
        
        // Кешируем на 1 час
        if (user != null) {
            cache.setex("user:" + userId, 3600, serializeUser(user));
        }
        
        return user;
    }
}

Лучшие практики

  1. Выбирайте правильный инструмент — не используйте MongoDB вместо Redis для кеша
  2. Планируйте индексы — они критичны для производительности
  3. Обрабатывайте консистентность данных — NoSQL часто жертвует ACID для масштабируемости
  4. Мониторьте производительность — особенно критично для распределённых систем
  5. Документируйте структуры — гибкая схема может привести к путанице
  6. Используйте миграции данных — для обновления структур при изменениях

Заключение

NoSQL базы данных — это мощный инструмент для решения специфичных задач. Важно понимать сильные стороны каждой БД и применять их целенаправленно в архитектуре приложения.