sub()
title: sub description: Subtrai um valor numérico de um campo existente
Section titled “title: sub description: Subtrai um valor numérico de um campo existente”sub() - Subtrair Valores
Section titled “sub() - Subtrair Valores”O método sub() subtrai um valor numérico de uma chave existente. Se a chave não existir, ela será criada com o valor negativo especificado.
Sintaxe
Section titled “Sintaxe”await db.sub(key, value)Parâmetros
Section titled “Parâmetros”- key (
string): A chave onde subtrair o valor - value (
number): O valor a ser subtraído
Retorno
Section titled “Retorno”- number: O novo valor após a subtração
Exemplos
Section titled “Exemplos”Subtração Básica
Section titled “Subtração Básica”const { HelperDB } = require('helper.db');const db = new HelperDB();
// Definir valor inicialawait db.set('balance', 1000);
// Subtrair valorconst newBalance = await db.sub('balance', 250);console.log(newBalance); // 750
// Verificar valor atualconst currentBalance = await db.get('balance');console.log(currentBalance); // 750Criação com Valor Negativo
Section titled “Criação com Valor Negativo”// Se a chave não existir, será criada com valor negativoconst result = await db.sub('debt', 100);console.log(result); // -100
// Subtrair maisawait db.sub('debt', 50);const totalDebt = await db.get('debt');console.log(totalDebt); // -150Valores Negativos
Section titled “Valores Negativos”// Usar valor negativo para somarawait db.set('score', 100);const newScore = await db.sub('score', -50);console.log(newScore); // 150 (subtração de negativo = soma)Decremento Unitário
Section titled “Decremento Unitário”// Decrementar contadorawait db.set('lives', 3);
// Simular perda de vidasfor (let i = 0; i < 2; i++) { await db.sub('lives', 1);}
const remainingLives = await db.get('lives');console.log(remainingLives); // 1Casos de Uso
Section titled “Casos de Uso”💰 Sistema de Compras
Section titled “💰 Sistema de Compras”async function processPurchase(userId, productId, price) { const userKey = `user:${userId}:balance`; const currentBalance = await db.get(userKey) || 0;
// Validar saldo if (currentBalance < price) { throw new Error('Saldo insuficiente'); }
// Debitar valor const newBalance = await db.sub(userKey, price);
// Registrar compra await db.push(`user:${userId}:purchases`, { productId, price, timestamp: new Date().toISOString(), balanceAfter: newBalance });
// Atualizar estatísticas await db.add('stats:total_sales', 1); await db.add('stats:revenue', price);
return { success: true, newBalance, purchaseId: Date.now() };}📦 Controle de Estoque
Section titled “📦 Controle de Estoque”async function sellProduct(productId, quantity) { const stockKey = `product:${productId}:stock`; const currentStock = await db.get(stockKey) || 0;
// Validar estoque if (currentStock < quantity) { throw new Error('Estoque insuficiente'); }
// Reduzir estoque const newStock = await db.sub(stockKey, quantity);
// Alertar se estoque baixo if (newStock < 10) { await db.push('alerts:low_stock', { productId, currentStock: newStock, timestamp: new Date().toISOString() }); }
// Registrar venda await db.push(`product:${productId}:sales`, { quantity, timestamp: new Date().toISOString(), stockAfter: newStock });
return { success: true, newStock };}🎮 Sistema de Vidas/Energia
Section titled “🎮 Sistema de Vidas/Energia”async function useEnergy(playerId, amount, action) { const energyKey = `player:${playerId}:energy`; const currentEnergy = await db.get(energyKey) || 100;
// Verificar energia suficiente if (currentEnergy < amount) { throw new Error('Energia insuficiente'); }
// Consumir energia const newEnergy = await db.sub(energyKey, amount);
// Registrar ação await db.push(`player:${playerId}:actions`, { action, energyUsed: amount, energyAfter: newEnergy, timestamp: new Date().toISOString() });
// Programar regeneração if (newEnergy < 100) { await scheduleEnergyRegen(playerId); }
return { newEnergy, canContinue: newEnergy > 0 };}
async function scheduleEnergyRegen(playerId) { const regenKey = `player:${playerId}:regen`; const lastRegen = await db.get(regenKey) || 0; const now = Date.now();
// Regenerar 1 energia por minuto if (now - lastRegen > 60000) { await db.add(`player:${playerId}:energy`, 1); await db.set(regenKey, now); }}📊 Controle de Cotas
Section titled “📊 Controle de Cotas”class QuotaManager { constructor(db) { this.db = db; }
async useQuota(userId, quotaType, amount) { const quotaKey = `quota:${userId}:${quotaType}`; const currentQuota = await this.db.get(quotaKey) || 0;
if (currentQuota < amount) { throw new Error(`Cota ${quotaType} insuficiente`); }
const newQuota = await this.db.sub(quotaKey, amount);
// Log de uso await this.db.push(`quota:${userId}:usage`, { type: quotaType, used: amount, remaining: newQuota, timestamp: new Date().toISOString() });
return { remaining: newQuota, used: amount }; }
async refillQuota(userId, quotaType, amount) { const quotaKey = `quota:${userId}:${quotaType}`; const newQuota = await this.db.add(quotaKey, amount);
await this.db.push(`quota:${userId}:refills`, { type: quotaType, added: amount, total: newQuota, timestamp: new Date().toISOString() });
return newQuota; }
async getQuotaStatus(userId) { const quotaTypes = ['api_calls', 'storage', 'bandwidth']; const status = {};
for (const type of quotaTypes) { const current = await this.db.get(`quota:${userId}:${type}`) || 0; const limit = await this.db.get(`quota:${userId}:${type}:limit`) || 1000;
status[type] = { current, limit, percentage: (current / limit) * 100 }; }
return status; }}🏆 Sistema de Penalidades
Section titled “🏆 Sistema de Penalidades”async function applyPenalty(userId, penaltyType, amount) { const penalties = { 'timeout': { field: 'reputation', multiplier: 1 }, 'warning': { field: 'reputation', multiplier: 0.5 }, 'ban': { field: 'reputation', multiplier: 2 } };
const penalty = penalties[penaltyType]; if (!penalty) { throw new Error('Tipo de penalidade inválido'); }
const adjustedAmount = amount * penalty.multiplier; const userKey = `user:${userId}:${penalty.field}`;
// Aplicar penalidade const newValue = await db.sub(userKey, adjustedAmount);
// Registrar penalidade await db.push(`user:${userId}:penalties`, { type: penaltyType, amount: adjustedAmount, field: penalty.field, newValue, timestamp: new Date().toISOString() });
// Verificar se precisa de ações adicionais if (newValue < 0) { await db.set(`user:${userId}:status`, 'suspended'); await db.push('admin:alerts', { type: 'user_suspended', userId, reason: `${penalty.field} negativo: ${newValue}`, timestamp: new Date().toISOString() }); }
return { newValue, suspended: newValue < 0 };}Performance
Section titled “Performance”- Complexidade: O(1) - Tempo constante
- Uso de memória: Mínimo
- Operação atômica: Segura para concorrência
- Ideal para: Decrementos e controle de recursos
⚠️ Considerações
Section titled “⚠️ Considerações”Validação de Saldo
Section titled “Validação de Saldo”async function safeSub(key, value, minValue = 0) { const current = await db.get(key) || 0;
if (current - value < minValue) { throw new Error(`Operação resultaria em valor abaixo do mínimo (${minValue})`); }
return await db.sub(key, value);}Operações Condicionais
Section titled “Operações Condicionais”async function conditionalSub(key, value, condition) { const current = await db.get(key) || 0;
// Verificar condição if (typeof condition === 'function' && !condition(current)) { throw new Error('Condição não atendida para subtração'); }
return await db.sub(key, value);}
// Usoawait conditionalSub('balance', 100, (current) => current >= 100);- Cria a chave se não existir (valor inicial será o valor negativo)
- Funciona apenas com valores numéricos
- Operação atômica em todos os drivers
- Valor negativo pode ser usado para soma
- Ideal para controle de recursos e decrementos
- Pode resultar em valores negativos