Artırma, Çarpma ve Min/Max Operatörleri
Öğrenenler, $inc, $mul, $min ve $max güncelleme operatörlerini kullanarak sayısal değişiklikleri atomik biçimde gerçekleştirecektir.
Artırma, Çarpma ve Min/Max Operatörleri, CoddyKit'te ücretsiz bir MongoDB Academy dersidir. Bu, 4 dersinin 2. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, MongoDB Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. MongoDB Academy kursu toplamda 4 dersten oluşur.
Bu dersin bazı bölümleri henüz çevrilmemiş olup İngilizce olarak gösterilmektedir.
Atomic Numeric Updates
A common application pattern is reading a numeric value, computing a new value, and writing it back. If done as separate read and write operations, a race condition can occur: two concurrent requests might both read the same value, compute different results, and overwrite each other.
MongoDB's numeric update operators—$inc, $mul, $min, and $max—perform numeric mutations atomically at the database level. The computation and write happen in a single operation, eliminating race conditions without needing application-level locking.
$inc: Increment and Decrement
The $inc operator increments a numeric field by a given amount. Pass a negative value to decrement. If the field does not exist, $inc creates it with the given increment value as the initial value (treating a missing field as 0).
Common uses: view counters, like counts, inventory decrement, score tracking, retry attempt counters. Because the increment is atomic, multiple concurrent requests can all safely call $inc on the same document without losing any increments—every request's change is applied.
// Increment page view counter
db.posts.updateOne(
{ slug: 'mongodb-intro' },
{ $inc: { views: 1 } }
);
// views: 100 -> 101 (atomic, safe under concurrent traffic)
// Decrement stock (atomic inventory deduction)
db.products.updateOne(
{ _id: productId, stock: { $gte: 1 } }, // Only if in stock
{ $inc: { stock: -1 } }
);
// Increment two fields at once
db.users.updateOne(
{ _id: userId },
{ $inc: { loginCount: 1, totalSessions: 1 } }
);Atomic Inventory Decrement Pattern
The atomic inventory decrement is a classic MongoDB pattern. The filter includes both the document identifier AND the minimum stock condition: { _id: productId, stock: { $gte: quantity } }. If the stock check fails (not enough inventory), the filter matches zero documents, modifiedCount is 0, and no inventory is decremented.
This pattern guarantees that you never decrement stock below zero, even under high concurrent load with many simultaneous purchase attempts. No application-level locks or transactions are needed for this single-document atomic check-and-decrement.
async function decrementStock(productId, quantity) {
const result = await db.collection('products').updateOne(
{
_id: new ObjectId(productId),
stock: { $gte: quantity } // Only if enough stock
},
{
$inc: { stock: -quantity }
}
);
if (result.modifiedCount === 0) {
throw new Error('INSUFFICIENT_STOCK');
}
return true; // Successfully decremented
}$mul: Multiply a Field
The $mul operator multiplies a numeric field by a given factor. Like $inc, it is atomic. If the field does not exist, $mul creates it with a value of 0 (not the multiplier—multiplying 0 by any factor is still 0, which is the mathematically correct behavior for a missing/zero field).
Practical uses: applying bulk price changes (multiply all prices by 1.05 for a 5% price increase), scaling scores or weights, adjusting currency values. $mul is much more efficient than fetching each document, multiplying in code, and writing back.
// Apply 5% price increase to all electronics products
db.products.updateMany(
{ category: 'Electronics' },
{ $mul: { price: 1.05 } }
);
// price: 100.00 -> 105.00 (atomically for each document)
// Apply 10% discount to sale items
db.products.updateMany(
{ onSale: true },
{ $mul: { price: 0.90 } }
);
// Multiply two fields at once
db.metrics.updateOne(
{ _id: metricId },
{ $mul: { valueA: 2, valueB: 0.5 } }
);$min: Conditional Set to Smaller Value
The $min operator updates a field only if the new value is less than the current value. If the current value is already smaller, the field is left unchanged. If the field does not exist, $min sets it to the provided value.
This is useful for tracking record lows, ensuring a value never exceeds a ceiling, or recording the earliest date. For example, tracking the minimum price a product has ever been sold for, or the earliest sign-in date for a user.
// Track the all-time lowest price seen for a product
db.products.updateOne(
{ _id: productId },
{ $min: { lowestPriceEver: currentSalePrice } }
);
// Only updates if currentSalePrice < lowestPriceEver
// If lowestPriceEver is 45 and currentSalePrice is 50: no change
// If lowestPriceEver is 45 and currentSalePrice is 39: updates to 39
// Record earliest login date
db.users.updateOne(
{ _id: userId },
{ $min: { firstLoginAt: new Date() } }
);$max: Conditional Set to Larger Value
The $max operator is the complement of $min: it updates a field only if the new value is greater than the current value. This is ideal for tracking high scores, peak values, and latest dates.
Common applications: leaderboard high scores (only update if the new score beats the current best), tracking the maximum concurrent users, or recording the most recent activity timestamp (ensuring you never overwrite a later event with an earlier one).
// Leaderboard: only update score if new score is higher
db.leaderboard.updateOne(
{ userId: userId },
{
$max: { highScore: newScore },
$set: { lastPlayedAt: new Date() }
}
);
// highScore: 9500. newScore: 8700 -> no change (8700 < 9500)
// highScore: 9500. newScore: 9800 -> updates to 9800
// Track most recent activity timestamp
db.users.updateOne(
{ _id: userId },
{ $max: { lastActiveAt: new Date() } }
);Combining Numeric Operators
You can combine multiple numeric update operators in a single update operation. They are all applied atomically together. For example, incrementing a counter while also ensuring a timestamp is updated to the latest value.
Combining $inc with $max/$min is a powerful pattern for metrics tracking: increment total event count while conditionally updating peak values, all in a single round-trip to the database.
// Update user metrics: increment logins, track latest/earliest dates
db.userMetrics.updateOne(
{ userId: userId },
{
$inc: { totalLogins: 1 },
$max: { lastLoginAt: new Date() },
$min: { firstLoginAt: new Date() }
},
{ upsert: true } // Create document if user has no metrics yet
);
// All three numeric operators apply atomically in one operationUsing $inc for Distributed Counters
A common architecture challenge is maintaining accurate counters (page views, likes, downloads) at high throughput. Using $inc atomically on a document is highly reliable but can become a write bottleneck if millions of requests hit the same document per second—because MongoDB uses document-level locking for writes.
Patterns to scale high-throughput counters: counter sharding (split the counter across N documents and sum them), buffered batching (accumulate increments in memory and flush periodically), or time-bucketed counters (one document per time period to distribute writes).
// Time-bucketed counter: one document per hour
const hourBucket = new Date();
hourBucket.setMinutes(0, 0, 0); // Round to current hour
db.pageViews.updateOne(
{ page: 'home', hour: hourBucket },
{ $inc: { count: 1 } },
{ upsert: true } // Create bucket if first view this hour
);
// Writes distribute across hourly documents,
// reducing contention vs a single global counterNumeric Operators in the Aggregation Pipeline
The arithmetic concepts behind $inc, $mul, $min, and $max also appear in the aggregation pipeline as expression operators and accumulator operators. In $project you can compute new numeric fields with $add, $multiply, $subtract. In $group you use $sum, $avg, $min, $max as accumulators.
Understanding the update operator semantics now makes the aggregation operators intuitive—they perform the same mathematical operations, just in a pipeline context rather than a write context.
// Aggregation: compute total revenue and max single order
db.orders.aggregate([
{ $match: { status: 'completed' } },
{
$group: {
_id: '$customerId',
totalSpent: { $sum: '$total' }, // Sum of all totals
orderCount: { $sum: 1 }, // Count documents
maxOrder: { $max: '$total' }, // Largest single order
minOrder: { $min: '$total' } // Smallest single order
}
}
]);Decimal Precision With $inc
When incrementing floating-point values with $inc, be aware of floating-point precision issues inherited from IEEE 754 double arithmetic. For financial amounts, always use NumberDecimal (BSON Decimal128) to avoid rounding errors.
Incrementing a Decimal128 field with $inc requires passing a NumberDecimal value in the shell or Decimal128.fromString in Node.js. The result will be exact decimal arithmetic without the floating-point drift that plagues 64-bit double arithmetic.
// Floating-point issue with double
// 0.1 + 0.2 = 0.30000000000000004 in IEEE 754!
db.accounts.updateOne(
{ _id: accountId },
{ $inc: { balance: 0.1 } } // Potential precision drift
);
// Correct: use Decimal128 for financial amounts
const { Decimal128 } = require('mongodb');
db.accounts.updateOne(
{ _id: accountId },
{ $inc: { balance: Decimal128.fromString('0.10') } }
);
// Exact decimal arithmetic - no floating point errorsAtomic Check-and-Update Patterns
A powerful MongoDB pattern is the conditional update with filter: include the condition you want to check as part of the query filter rather than reading first and deciding in application code. This makes the check-and-update atomic, eliminating race conditions.
Patterns: decrement stock only if sufficient quantity (filter includes stock: { : qty }), update only if a field has a specific value (optimistic locking pattern), or apply a promotion only if the user has not already received it. The operation either succeeds (modifiedCount: 1) or the condition was not met (modifiedCount: 0).
// Optimistic locking: update only if version matches
async function updateWithLock(id, currentVersion, newData) {
const result = await db.collection('items').updateOne(
{ _id: id, version: currentVersion }, // Version check in filter!
{
: { ...newData },
: { version: 1 } // Increment version on each update
}
);
if (result.modifiedCount === 0) {
throw new Error('VERSION_CONFLICT');
// Another process updated this document since we read it
}
}Quick Check
Test your understanding of MongoDB & NoSQL Databases concepts from this lesson.
Lesson Recap
In this lesson you learned: $inc atomically increments or decrements a numeric field—ideal for counters, view counts, and inventory decrements combined with a stock-check filter to prevent over-selling, $mul multiplies a field by a factor for bulk price adjustments and scaling operations, and $min/$max conditionally update only when the new value is smaller/larger than the current—perfect for tracking all-time records, high scores, and earliest/latest timestamps. Next up we explore array update operators: $push, $pull, and $addToSet.
Sıkça Sorulan Sorular
“Artırma, Çarpma ve Min/Max Operatörleri” dersi ücretsiz mi?
Evet — “Artırma, Çarpma ve Min/Max Operatörleri” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve MongoDB Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. MongoDB Academy kursu toplamda 4 dersten oluşur.
“Artırma, Çarpma ve Min/Max Operatörleri” dersinde ne öğreneceğim?
Öğrenenler, $inc, $mul, $min ve $max güncelleme operatörlerini kullanarak sayısal değişiklikleri atomik biçimde gerçekleştirecektir. MongoDB Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
MongoDB Academy öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te MongoDB Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 2. dersidir.
“Artırma, Çarpma ve Min/Max Operatörleri” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu MongoDB Academy dersinde kod yazıp çalıştırabilir miyim?
Evet. Her MongoDB Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- $set ve $unset ile updateOne ve updateMany
- Artırma, Çarpma ve Min/Max Operatörleri
- Dizi Güncelleme Operatörleri: $push, $pull, $addToSet
- deleteOne ve deleteMany ile Belgeleri Güvenle Silme