iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

replaceOne

replaceOne vs updateOne in MongoDB. When each is right, and the surprises that bite when you mix them up.

MongoDB — replaceOne

EXAMPLE
// ===== updateOne =====
// Modifies SPECIFIC fields using update operators.
db.users.updateOne(
  { _id: ObjectId('...') },
  { $set: { name: 'Alex Chen' }, $inc: { logins: 1 } }
);
// Other fields are UNCHANGED.

// ===== replaceOne =====
// Replaces the WHOLE document (except _id).
db.users.replaceOne(
  { _id: ObjectId('...') },
  { name: 'Alex Chen', email: 'alex@example.com', logins: 1 }
);
// Any fields not in the replacement document are GONE.

// ===== When to use replaceOne =====
// - Rewriting an entire entity (whole DTO from the API)
// - Bulk migrations where shape changes
// - You explicitly want to drop deprecated fields

// ===== When to use updateOne =====
// - Modifying one or a few fields
// - Atomic operators ($inc, $push, $pull, $addToSet, $set, $unset)
// - Partial updates from PATCH-style APIs

// ===== Filter + immutable _id =====
// The filter must match exactly ONE document for *One variants.
// _id cannot be changed by replaceOne (it errors if you try).
db.users.replaceOne(
  { _id: oldId },
  { _id: newId, ... }   // throws
);

// ===== Upsert =====
db.users.replaceOne(
  { email: 'alex@example.com' },
  { email: 'alex@example.com', name: 'Alex' },
  { upsert: true }
);
// If no doc matches the filter, the replacement is INSERTED.

// ===== Common driver examples =====
// Node:
import { MongoClient } from 'mongodb';
const client = new MongoClient(uri); await client.connect();
const users = client.db('shop').collection('users');

await users.replaceOne(
  { _id: id },
  { name: 'Alex', email: 'a@x.io' },
);
await users.updateOne(
  { _id: id },
  { $set: { lastLogin: new Date() } },
);

// Python:
from pymongo import MongoClient
c = MongoClient(uri)
users = c.shop.users
users.replace_one({'_id': id}, {'name': 'Alex'})
users.update_one({'_id': id}, {'$set': {'lastLogin': datetime.utcnow()}})

// ===== Mass replace =====
// There is no replaceMany. For bulk operations, use:
//   bulkWrite + replaceOne entries, OR
//   updateMany + $set / $unset for partial rewrites

// ===== Patterns to internalise =====
// - updateOne for surgical changes; replaceOne for whole-doc rewrites
// - findOneAndUpdate / findOneAndReplace for read-after-write
// - Upsert when you want INSERT-or-UPDATE in one round trip
// - bulkWrite for batches

// ===== Pitfalls =====
// - replaceOne with a missing field -> the existing field is GONE
// - Forgetting that 'updateOne' without operators is a syntax error
// - Trying to change _id with replaceOne -> exception
// - Race conditions on read-then-write; prefer atomic update operators

Why it matters

updateOne for partial changes; replaceOne for whole-doc rewrites. Mix them up and you silently drop fields. When the API speaks PATCH, use updateOne with $set; when it speaks PUT, use replaceOne. Upsert is the third option that combines insert and update in one round trip.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
db.customers.replaceOne({ _id: id }, { name: 'Ada', age: 36 });
Try it Yourself »

Discussion

Loading…