Deleting Documents and Getting Started with Node.js

Deleting documents is a core operation in data cleanup—this course also introduces hands-on practice with Node.js and Mongoose.

Master deleteOne/deleteMany, connecting Node.js and Mongoose, schema definition, and model CRUD operations.

1. What You'll Learn


2. A True Story of a Full-Stack Engineer

(1) Pain Point: Cleaning up expired data requires complex scripts

Bob needs to regularly clean up expired orders and deactivated user accounts on the e-commerce platform:

JAVASCRIPT
// ❌ Counterexample:Query multiple times, then delete(Slow + Race Condition)
const expiredOrders = await Order.find({ expiryDate: { $lt: new Date() } });
for (const order of expiredOrders) {
  await Order.deleteOne({ _id: order._id });
}
// N Sub-network round trip,N Second deletion operation

(2) Solution for Batch Deletions in MongoDB + Mongoose

JAVASCRIPT
// ✅ Correct Example:Bulk Deletion in One Go
const result = await Order.deleteMany({
  expiryDate: { $lt: new Date() }
});
// Delete all expired orders in a single operation

// mongoose Schema Definition
const OrderSchema = new mongoose.Schema({
  userId: { type: mongoose.Schema.Types.ObjectId, required: true },
  items: [{ sku: String, qty: Number, price: mongoose.Schema.Types.Decimal128 }],
  total: { type: mongoose.Schema.Types.Decimal128, required: true },
  status: { type: String, enum: ['pending', 'paid', 'shipped', 'delivered'], default: 'pending' },
  expiryDate: Date,
  createdAt: { type: Date, default: Date.now }
}, { timestamps: true });

const Order = mongoose.model('Order', OrderSchema);

100%
graph LR
    A[Delete Operation] --> B[deleteOne<br/>Delete a single item]
    A --> C[deleteMany<br/>Bulk Delete]
    A --> D[findOneAndDelete<br/>Atom Returns]
    A --> E[drop<br/>Delete Set]
    A --> F[dropDatabase<br/>Delete the database]

    style D fill:#d4edda

3. deleteOne: Delete a Single Document

Concept Explanation: deleteOne Deletes the first document that matches the filter criteria; this is the most basic deletion method in MongoDB. Deletion is irreversible—there is no "recycle bin" mechanism, and deleted documents cannot be directly restored (unless a backup or oplog is available). Therefore, deletion operations must be performed with extreme caution in production environments.

How It Works: deleteOne The execution flow is as follows: Matching phase (find the first document based on the filter) → Deletion phase (remove the document from the collection) → Index update (delete the relevant index entries) → Write Concern confirmation. The entire operation is atomic for a single document. After deletion, disk space is not immediately freed up but is marked as reusable space.

100%
sequenceDiagram
    participant App as Applications
    participant Mongo as MongoDB
    participant WT as WiredTiger

    App->>Mongo: deleteOne({ sku: "PHONE-001" })
    Mongo->>Mongo: Match filter (Index Scan)
    Mongo->>WT: Delete Document + Update Index
    WT-->>Mongo: Confirm Deletion
    Mongo-->>App: { acknowledged: true, deletedCount: 1 }
Parameter Type Description
filter Document Search Criteria (Required)
options Document writeConcern etc.(optional)
Return Field Type Description
acknowledged Boolean Whether the write has been confirmed
deletedCount Number Number of documents deleted (0 or 1)
JAVASCRIPT
// === deleteOne Basic Usage ===
db.products.deleteOne({ sku: 'PHONE-001' });

// Return Results:
// { acknowledged: true, deletedCount: 1 }
Return Field Meaning
acknowledged Has this been confirmed?
deletedCount Number of deleted documents (0 or 1)

▶ Example 1: deleteOne in Action

JAVASCRIPT
// === Delete Specified _id the document ===
db.users.deleteOne({ _id: ObjectId('507f1f77bcf86cd799439011') });

// === Delete Based on Specified Criteria(First match)===
db.logs.deleteOne({ level: 'debug' });

// === mongoose Equivalent ===
const result = await Product.deleteOne({ sku: 'PHONE-001' });
console.log(result.deletedCount);  // 1

4. deleteMany: Batch Deletion

Concept Description: deleteMany deletes all documents that match the filter criteria and is the core method for batch data cleanup. Unlike deleteOne, which deletes only the first matching document, deleteMany can delete tens of thousands of documents at once. Common use cases include cleaning up expired logs, deleting data for deactivated users, and removing test data.

How It Works: deleteMany First, it retrieves all matching documents, then deletes them one by one. The deletion process is not transactional—if it fails midway, the documents that have already been deleted will not be restored. For bulk deletions, it is recommended to execute them in batches to avoid locking the collection for an extended period.

Dimension deleteOne deleteMany
Match Range First Match All Matches
Number of Deletions 0 or 1 0 to N
Use Cases Delete a Single Item Bulk Cleanup
Risk Low Moderate (significant impact from user error)
JAVASCRIPT
// === deleteMany Basic Usage ===
db.products.deleteMany({ category: 'Discontinued' });

// === Delete all expired orders ===
db.orders.deleteMany({
  expiryDate: { $lt: new Date() }
});

// === Delete Multiple Documents That Meet Specific Criteria ===
db.logs.deleteMany({
  level: { $in: ['debug', 'info'] },
  createdAt: { $lt: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) }
});

▶ Example 2: deleteMany in Practice

JAVASCRIPT
// === Cleanup 30 Entries from a few days ago ===
const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
const result = await Log.deleteMany({ createdAt: { $lt: thirtyDaysAgo } });
console.log(`Deleted ${result.deletedCount} old logs`);

// === Delete the session of a logged-out user ===
await Session.deleteMany({ userId: deletedUserId });

// === Delete all documents from the entire collection(Use with caution!)===
db.products.deleteMany({});
// ⚠️ This will delete products All documents in the collection

5. findOneAndDelete Atomic Return

Concept Description: findOneAndDelete is a special deletion method that returns the content of the deleted document at the same time it deletes it. This resolves the race condition associated with "query first, then delete"—the traditional approach requires first findOne retrieving the document and then deleteOne deleting it, during which time the document may be modified or deleted by other operations. findOneAndDelete combines the query and delete into a single atomic operation.

How It Works: findOneAndDelete performs an atomic operation at the document level: locate the matching document → record the document content → delete the document → return the recorded content. By default, it returns the document’s state prior to deletion; the projection option can be used to control which fields are returned.

100%
graph TB
    A[Need to delete and retrieve a document] --> B{Method Selection}
    B --> C[❌ Check First, Then Delete<br/>findOne + deleteOne<br/>Competitive Conditions Risk]
    B --> D[✅ findOneAndDelete<br/>Atomic Manipulation<br/>No risk of competition]
    B --> E[✅ findOneAndDelete + sort<br/>Atomic Manipulation + Order<br/>FIFO Queue]

    style D fill:#d4edda
    style E fill:#d4edda
Advantage Description
Atomicity Query and delete are performed in a single operation, avoiding race conditions
Return Document Retrieve the deleted document directly, without the need for a secondary query
Sorting Support Enables ordered consumption when used with the sort option
Use Cases Queue tasks, message consumption, inventory deduction
JAVASCRIPT
// === findOneAndDelete Atomic Manipulation ===
const deletedDoc = db.products.findOneAndDelete({ sku: 'PHONE-001' });

// Restore Deleted Documents(Status before default deletion)
console.log(deletedDoc);
// { _id: ..., sku: 'PHONE-001', title: 'Phone', price: 599, ... }

// === Return if it does not exist null ===
const result = db.products.findOneAndDelete({ sku: 'NOT_EXIST' });
console.log(result);  // null
Advantage Description
Atomicity Query and delete are performed in a single operation, avoiding race conditions
Return Document Retrieve the deleted document directly, without the need for a secondary query
Use Cases Queue tasks, message consumption, inventory deduction

▶ Example 3: findOneAndDelete in Action

JAVASCRIPT
// === Scene:Message Queue(FIFO)===
const message = await Queue.findOneAndDelete(
  { status: 'pending' },
  { sort: { createdAt: 1 } }  // Consume the oldest ones first
);

// === Scene:Claim a Mission ===
const task = await Task.findOneAndDelete({
  status: 'available',
  assignee: null
});
if (task) {
  console.log(`Claimed task: ${task._id}`);
}

// === mongoose Equivalent ===
const message = await Queue.findOneAndDelete(
  { status: 'pending' },
  { sort: { createdAt: 1 } }
);

6. drop Collection and dropDatabase

Conceptual Explanation: drop and dropDatabase are the most thorough deletion operations—drop deletes an entire collection (including all documents and indexes), and dropDatabase deletes the entire database (including all collections). Unlike deleteMany({}), the drop operation not only deletes the data but also deletes the collection’s metadata (index definitions, schema validation rules, capped settings, etc.).

Comparative Analysis:

Dimension deleteMany({}) drop() dropDatabase()
Deletion Scope All documents in the collection The entire collection The entire database
Retain Index ✅ Retain ❌ Delete All ❌ Delete All
Keep "capped" setting ✅ Keep ❌ Delete ❌ Delete
Keep Schema Validation ✅ Keep ❌ Delete ❌ Delete
Speed Slow (deletes one by one) Fast (frees up space immediately) Fast
Recoverability Can be recovered via the oplog Extremely difficult to recover Extremely difficult to recover
JAVASCRIPT
// === Delete Set ===
db.products.drop();
// true(Success)or false(The set does not exist)

// === Delete the database ===
db.dropDatabase();
// { "dropped" : "shopdb", "ok" : 1 }

// === Use with caution: Delete all data from the entire collection but keep the collection itself ===
db.products.deleteMany({});
// Equivalent but preserves the set structure(Index、capped Settings)

▶ Example 4: Choosing Between drop and deleteMany

JAVASCRIPT
// Scene:Cleaning Up Temporary Test Sets
// ✅ Recommendations:drop(Delete Set+Index,Clean)
db.test_results.drop();

// ✅ Preserve the collection structure:deleteMany(Clear the document only)
db.user_sessions.deleteMany({});

7. Node.js + Mongoose: Connecting to MongoDB

Concept Overview: Mongoose is the most popular MongoDB ODM (Object Document Modeling) in the Node.js ecosystem, offering advanced features such as schema definition, data validation, middleware, and join queries. This section begins with connecting to MongoDB and gradually introduces the core concepts of Mongoose.

How It Works: The process by which Mongoose connects to MongoDB consists of the following steps: creating a connection instance → establishing a TCP connection → authentication (if required) → selecting a database → initializing the connection pool → triggering the connected event. By default, Mongoose maintains a connection pool (typically 5–100 connections) and reuses connections to avoid frequently establishing and closing TCP connections.

100%
sequenceDiagram
    participant App as Node.js Applications
    participant Mongoose as mongoose
    participant Mongo as MongoDB

    App->>Mongoose: mongoose.connect(uri)
    Mongoose->>Mongo: Establish TCP Connect
    Mongo-->>Mongoose: Connection Confirmation
    Mongoose->>Mongo: Certification(If you need)
    Mongo-->>Mongoose: Authentication Successful
    Mongoose->>Mongoose: Initialize the connection pool
    Mongoose-->>App: Trigger 'connected' Event
    Note over App,Mongoose: Connection Ready,Executable CRUD
Connection Method URI Format Use Cases
Local Standalone mongodb://localhost:27017/shopdb Development Environment
Atlas Cloud mongodb+srv://user:pass@cluster0.mongodb.net/mydb Production/Team
Instance Set mongodb://host1,host2,host3/shopdb?replicaSet=rs0 Production Environment
Docker mongodb://192.168.1.100:27017/shopdb Containerized Deployment

(1) Install Mongoose

BASH
npm install mongoose --save

(2) Connecting to MongoDB

JAVASCRIPT
// === Basic Connections ===
const mongoose = require('mongoose');

async function connectDB() {
  await mongoose.connect('mongodb://localhost:27017/shopdb');
  console.log('✅ MongoDB connected');
}

connectDB().catch(err => console.error('❌ Connection error:', err));

(3) Connection Options

Concept Explanation: Mongoose connection options control key parameters that govern connection behavior—such as timeout, connection pool size, and authentication methods. These options must be configured appropriately in production environments; otherwise, they may result in connection leaks, timeout failures, or authentication errors.

Key Parameter Descriptions:

Parameter Default Value Description Production Recommendation
serverSelectionTimeoutMS 30000 Server selection timeout (milliseconds) 5000
socketTimeoutMS 30,000 Socket timeout 45,000
maxPoolSize 100 Maximum connection pool size 50–100
minPoolSize 0 Minimum connection pool size 5
heartbeatFrequencyMS 10,000 Heart Rate Monitoring Frequency 10,000
retryWrites true Automatic write retry true
authSource admin Authentication Database As configured

Connection Pooling Principle: Mongoose maintains a TCP connection pool to avoid the overhead of frequently creating and destroying connections. Each concurrent request retrieves a connection from the pool and returns it once the request is complete. maxPoolSize Control the maximum number of concurrent connections—setting this value too low will cause requests to queue up, while setting it too high will consume excessive server resources.

JAVASCRIPT
// === Complete Connection Configuration ===
await mongoose.connect('mongodb://localhost:27017/shopdb', {
  // Server selection timeout
  serverSelectionTimeoutMS: 5000,

  // Socket Timeout
  socketTimeoutMS: 45000,

  // Connection Pool Size
  maxPoolSize: 50,
  minPoolSize: 5,

  // Automatic Reconnection
  autoReconnect: true,

  // Certification(If enabled)
  user: 'admin',
  pass: 'password',

  // Certification Database
  authSource: 'admin'
});

(4) Connect to Atlas

JAVASCRIPT
// === Atlas Concatenate Strings ===
await mongoose.connect(
  'mongodb+srv://user:pass@cluster0.mongodb.net/mydb?retryWrites=true&w=majority'
);

// === With environment variables ===
require('dotenv').config();
await mongoose.connect(process.env.MONGODB_URI);

▶ Example 5: Complete Connection Management

JAVASCRIPT
// db.js
const mongoose = require('mongoose');

const connectDB = async () => {
  try {
    const conn = await mongoose.connect(process.env.MONGODB_URI || 'mongodb://localhost:27017/shopdb', {
      serverSelectionTimeoutMS: 5000,
      maxPoolSize: 50
    });
    console.log(`✅ MongoDB connected: ${conn.connection.host}`);

    // Listening for Connection Events
    mongoose.connection.on('error', (err) => console.error('❌ MongoDB error:', err));
    mongoose.connection.on('disconnected', () => console.warn('⚠️ MongoDB disconnected'));
    mongoose.connection.on('reconnected', () => console.log('🔄 MongoDB reconnected'));
  } catch (err) {
    console.error('❌ Connection failed:', err.message);
    process.exit(1);
  }
};

const disconnectDB = async () => {
  await mongoose.disconnect();
  console.log('MongoDB disconnected');
};

module.exports = { connectDB, disconnectDB, mongoose };

8. Mongoose Schema Definition

Concept Explanation: A schema is a core concept in Mongoose—it defines a document’s field types, validation rules, default values, indexes, and more. Although MongoDB itself is schema-less, Mongoose provides schema constraints at the application layer to prevent dirty data and type errors. Once defined, a schema is compiled into a model, which serves as the interface for interacting with the database.

How It Works: Schema → Model → Document is Mongoose’s three-tier architecture. The Schema defines the structure (field types and validation); the Model is the compiled result of the Schema (corresponding to a collection); and the Document is an instance of the Model (corresponding to a document). The Schema does not directly interact with the database; CRUD operations can only be performed through the Model.

Schema Options: The second parameter of the Schema constructor controls global behavior—timestamps: true automatically adds createdAt/updatedAt, strict: true ignores undeclared fields, and versionKey: false removes the __v version key.

100%
graph LR
    A[Schema<br/>Define Field Types+Verification] -->|mongoose.model| B[Model<br/>Interfaces for Operation Sets]
    B -->|new Model| C[Document<br/>An Example Document]
    B -->|Model.find| D[Search Results<br/>Document Array]

    style A fill:#cce5ff
    style B fill:#d4edda
Schema Field Options Type Description Example
type Constructor Field type String, Number, Date
required Boolean/Array Required [true, 'Email is required']
default Any/Function Default Value Date.now, 0, true
unique Boolean Whether to create a unique index true
index Boolean/Object Create Index true, { sparse: true }
enum Array List of allowed values ['pending', 'paid']
min / max Number Value Range min: 0, max: 999999
minlength / maxlength Number String length range minlength: 3
match RegExp Regular Expression Validation /^.+@.+$/
select Boolean Whether the default query returns false (e.g., passwordHash)
validate Function Custom validation function v => v.length >= 8
get / set Function Virtual getter/setter get: v => v.toString()

(1) Basic Schema

JAVASCRIPT
// === Schema Defining the User Model ===
const UserSchema = new mongoose.Schema({
  // Field Definitions
  email: {
    type: String,
    required: true,
    unique: true,
    lowercase: true,
    trim: true
  },
  username: {
    type: String,
    required: true,
    unique: true,
    minlength: 3,
    maxlength: 30
  },
  passwordHash: {
    type: String,
    required: true,
    select: false  // The default query returns no results.
  },
  age: {
    type: Number,
    min: 0,
    max: 150
  },
  role: {
    type: String,
    enum: ['customer', 'admin', 'moderator'],
    default: 'customer'
  },
  isActive: {
    type: Boolean,
    default: true
  }
}, {
  // Schema Options
  timestamps: true,           // Auto-add createdAt/updatedAt
  collection: 'users',       // Explicitly Specify the Set Name
  strict: true,              // Strict Mode(Do not save undeclared fields)
  versionKey: false          // Disable __v
});

(2) Schema Types

JAVASCRIPT
const ProductSchema = new mongoose.Schema({
  // String
  sku: String,

  // Numbers
  stock: Number,
  price: mongoose.Schema.Types.Decimal128,

  // Date
  releaseDate: Date,

  // Boolean
  isActive: Boolean,

  // Array
  tags: [String],

  // Nested Documents
  specs: {
    screen: String,
    battery: String
  },

  // Buffer(Binary)
  thumbnail: Buffer,

  // ObjectId Quote
  categoryId: mongoose.Schema.Types.ObjectId,

  // Mixed Type(Any)
  metadata: mongoose.Schema.Types.Mixed,

  // Map(Key-value pairs)
  translations: {
    type: Map,
    of: String
  }
});

▶ Example 6: Comprehensive Schema Design

JAVASCRIPT
const ProductSchema = new mongoose.Schema({
  sku: {
    type: String,
    required: [true, 'SKU is required'],
    unique: true,
    index: true,
    match: /^[A-Z0-9-]+$/
  },
  title: {
    type: String,
    required: true,
    trim: true,
    maxlength: 200
  },
  description: {
    type: String,
    maxlength: 5000
  },
  price: {
    type: mongoose.Schema.Types.Decimal128,
    required: true,
    min: 0,
    get: v => v ? v.toString() : v  // Serialize to a string
  },
  category: {
    type: String,
    enum: ['Electronics', 'Books', 'Clothing', 'Home'],
    required: true,
    index: true
  },
  tags: [String],
  attributes: {
    type: Map,
    of: mongoose.Schema.Types.Mixed,
    default: {}
  },
  stock: {
    type: Number,
    default: 0,
    min: 0
  },
  rating: {
    type: Number,
    default: 0,
    min: 0,
    max: 5
  },
  isActive: {
    type: Boolean,
    default: true,
    index: true
  }
}, {
  timestamps: true,
  toJSON: { virtuals: true, getters: true },
  toObject: { virtuals: true }
});

// Virtual Fields
ProductSchema.virtual('isInStock').get(function() {
  return this.stock > 0;
});

// Index
ProductSchema.index({ category: 1, price: 1 });
ProductSchema.index({ title: 'text', description: 'text' });

const Product = mongoose.model('Product', ProductSchema);

9. mongoose CRUD Operations

Concept Explanation: CRUD (Create/Read/Update/Delete) is the basic pattern for database operations. Mongoose provides two CRUD styles—Model static methods (such as Model.create() and Model.find()) and Document instance methods (such as doc.save() and doc.remove()). Static methods operate directly on the database, while instance methods first modify the in-memory object and then synchronize the changes to the database.

Comparative Analysis:

Dimension Model static methods Document instance methods
Calling method Model.create(data) new Model(data); doc.save()
Trigger Verification
Triggered Middleware Partial ✅ All
Return Value Document or result object Document
Use Cases Simple CRUD Complex Business Logic
100%
graph TB
    A[mongoose CRUD] --> B[Create<br/>create() / save()]
    A --> C[Read<br/>find() / findOne() / findById()]
    A --> D[Update<br/>updateOne() / findByIdAndUpdate()]
    A --> E[Delete<br/>deleteOne() / findByIdAndDelete()]

    style A fill:#cce5ff

(1) Create

JAVASCRIPT
// === model.create() Create a Single Document ===
const user = await User.create({
  email: 'alice@example.com',
  username: 'alice_chen',
  passwordHash: 'hashed_password',
  age: 28
});
console.log(user._id);  // ObjectId

// === Create Multiple Documents ===
const users = await User.create([
  { email: 'bob@example.com', username: 'bob' },
  { email: 'charlie@example.com', username: 'charlie' }
]);

// === new + save Pattern ===
const user = new User({
  email: 'alice@example.com',
  username: 'alice_chen'
});
await user.save();

(2) Read

JAVASCRIPT
// === find Search for multiple ===
const users = await User.find({ isActive: true });

// === findOne Query a single ===
const user = await User.findOne({ email: 'alice@example.com' });

// === findById Through _id Search ===
const user = await User.findById('507f1f77bcf86cd799439011');

// === Chain Query ===
const products = await Product.find({ category: 'Electronics' })
  .select('sku title price')
  .sort({ price: 1 })
  .limit(20)
  .lean();

(3) Update

JAVASCRIPT
// === findByIdAndUpdate ===
const user = await User.findByIdAndUpdate(
  userId,
  { $set: { lastLoginAt: new Date() } },
  { new: true, runValidators: true }  // Return to the updated document
);

// === updateOne ===
const result = await User.updateOne(
  { email: 'alice@example.com' },
  { $set: { age: 29 } }
);

// === save() Replace the entire document ===
const user = await User.findById(userId);
user.age = 30;
await user.save();

(4) Delete

JAVASCRIPT
// === findByIdAndDelete ===
const user = await User.findByIdAndDelete(userId);

// === deleteOne ===
const result = await User.deleteOne({ email: 'alice@example.com' });

// === deleteMany ===
const result = await User.deleteMany({ isActive: false });

▶ Example 7: A Complete CRUD Practical Exercise

JAVASCRIPT
// === 1. Create a User ===
const alice = await User.create({
  email: 'alice@example.com',
  username: 'alice_chen',
  passwordHash: await bcrypt.hash('password123', 10),
  age: 28
});

// === 2. Query User ===
const users = await User.find({ age: { $gte: 18 } })
  .select('email username age')
  .lean();

// === 3. Update User ===
await User.updateOne(
  { _id: alice._id },
  { $set: { lastLoginAt: new Date() }, $inc: { loginCount: 1 } }
);

// === 4. Delete Test User ===
await User.deleteMany({ email: { $regex: '@test\\.com$' } });

10. Troubleshooting Common Errors

Concept Overview: The four most common types of errors encountered when developing with Node.js and Mongoose are: connection errors (ECONNREFUSED), unique index conflicts (E11000), schema validation failures (ValidationError), and type conversion failures (CastError). Understanding the root causes of these errors and how to handle them is a fundamental skill in Mongoose development.

Error Handling Strategy: Connection errors require a retry mechanism; unique index conflicts require an UPSERT or front-end validation; schema validation failures require improved form validation; and CastErrors require checking the ObjectId format. All errors should be caught at the application layer and return user-friendly error messages—do not expose the raw MongoDB error stack trace to front-end users.

100%
graph TB
    A[mongoose Error] --> B[Connection Error<br/>ECONNREFUSED]
    A --> C[Unique Index Conflict<br/>E11000]
    A --> D[Verification Failed<br/>ValidationError]
    A --> E[Type conversion failed<br/>CastError]
    
    B --> B1[Inspection mongod Enable or Disable<br/>Check the connection string]
    C --> C1[Usage upsert<br/>Front-End Uniqueness Validation]
    D --> D1[Improve Schema Verification<br/>Front-End Form Validation]
    E --> E1[Inspection ObjectId Format<br/>Verify Parameter Types]
Error Cause Solution
MongooseServerSelectionError: connect ECONNREFUSED MongoDB is not running brew services start mongodb-community@7.0
MongoError: E11000 duplicate key error Unique Index Conflict Check for duplicate field values
ValidationError: Path 'email' is required Required fields are missing Please fill in the required fields
CastError: Cast to ObjectId failed _id format error Check the ObjectId string format

❓ FAQ

Q Which is better, deleteOne or findOneAndDelete?
A Use findOneAndDelete if you need to return the deleted document; use deleteOne if you just want to delete it. Both have comparable performance.
Q Do Mongoose connections need to be closed?
A Yes. Call mongoose.disconnect() or mongoose.connection.close() when the process exits to ensure that all connections are gracefully closed.
Q If a field is changed in the schema, does the database need to be migrated?
A No. The Mongoose schema is defined at the application layer and does not affect the database. MongoDB is schema-less, so new fields are automatically added. However, old documents may be missing the new fields, so the application layer must handle this undefined.
Q What is the performance impact of lean()?
A lean() skips Mongoose document hydration and returns a pure JavaScript object. This results in a 3-5x performance boost, but you lose access to Mongoose document methods (such as save() and populate()). It is suitable for pure query APIs.
Q What is the difference between Model.create and new Model + save?
A Both trigger schema validation and middleware. The Model.create() syntax is more concise, while new + save is better suited for scenarios requiring step-by-step operations.

📖 Summary


📝 Exercises

  1. Basic Question (⭐): Use deleteOne to delete the product with the SKU 'TEST-001'.
  2. Basic Questions (⭐): Define the Product model using Mongoose Schema (including sku, title, price, category, and stock), and execute create, find, update, and delete operations.
  3. Advanced Problem (⭐⭐): Write a Node.js script to periodically clean up expired orders that are more than 30 days old (using deleteMany).
  4. Advanced Problem (⭐⭐): Implement a message queue: Use findOneAndDelete with sort: { createdAt: 1 } to implement FIFO consumption.
  5. Challenge (⭐⭐⭐): Implement a user registration feature using Mongoose, Schema, and middleware (including email uniqueness validation, bcrypt password hashing, and timestamping).
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏