insertOne() - Insert a single document

Syntax

collection(name).insertOne(document, options?)

Parameters

document (required)

Type: Object

The document object to be inserted. If the document does not have a _id field, MongoDB will automatically generate one.

//Automatically generate _id
await collection("users").insertOne({
  name: "Alice",
  email: "alice@example.com",
  age: 30
});

//Manually specify _id
await collection("users").insertOne({
  _id: "custom-id-123",
  name: "Bob",
  email: "bob@example.com"
});

options (optional)

Type: Object

OptionsTypeDefaultDescription
writeConcernObject-Write follow options
bypassDocumentValidationbooleanfalseWhether to bypass document verification
commentstring-Operation comments, used for log tracking

Return value

Type: Promise<Object>

Return an object containing the results of the insertion:

{
  insertedId: ObjectId("507f1f77bcf86cd799439011"),  //Insert the _id of the document
  acknowledged: true                                  //Is the operation confirmed?
}

Core Features

✅ Automatically generate _id

If the document does not have a _id field, MongoDB automatically generates a unique ObjectId.

const result = await collection("users").insertOne({
  name: "Alice",
  email: "alice@example.com"
});

console.log(result.insertedId); // ObjectId("507f1f77bcf86cd799439011")

✅ Explicit cache invalidation

After the insertion succeeds, monSQLize does not clear query caches by default. Use cache.invalidate or autoInvalidate: true when the write should clear cache.

//Query and cache
const users = await collection("users").find({}, { cache: 5000 });
console.log(users.length); // 10

//Insert new user and precisely clear the cached query when needed
await collection("users").insertOne(
  { name: "Alice" },
  {
    cache: {
      invalidate: [{
        operation: "find",
        query: {},
        options: { cache: 5000 }
      }]
    }
  }
);

//Query again (will not return from cache, will query the database)
const updatedUsers = await collection("users").find({}, { cache: 5000 });
console.log(updatedUsers.length); // 11

✅ Slow query monitoring

Insert operations that exceed a threshold (default 1000ms) automatically log warnings.

//Configure slow query threshold
const monsqlize = new MonSQLize({
  slowQueryMs: 500  //Log warning after more than 500ms
});

//Slow insert operations will be logged
await collection("large_docs").insertOne({
  data: { /* large amount of data */ }
});
//Log: [WARN] [insertOne] Slow operation warning { duration: 650ms, ... }

Common scenarios

Scenario 1: Create new user

const result = await collection("users").insertOne({
  userId: "user123",
  name: "Alice",
  email: "alice@example.com",
  status: "active",
  createdAt: new Date()
});

console.log("User created successfully, ID:", result.insertedId);

Scenario 2: Inserting nested documents

const result = await collection("orders").insertOne({
  orderId: "order123",
  customerId: "cust456",
  items: [
    { productId: "prod1", quantity: 2, price: 29.99 },
    { productId: "prod2", quantity: 1, price: 49.99 }
  ],
  shippingAddress: {
    street: "123 Main St",
    city: "New York",
    zip: "10001"
  },
  total: 109.97,
  createdAt: new Date()
});

console.log("Order created successfully:", result.insertedId);

Scenario 3: Using custom _id

//Use business ID as _id
const result = await collection("products").insertOne({
  _id: "SKU-12345",
  name: "Laptop",
  price: 999.99,
  category: "electronics"
});

console.log("Product ID:", result.insertedId); // "SKU-12345"

Scenario 4: Inserting timestamped documents

const result = await collection("logs").insertOne({
  level: "info",
  message: "User logged in",
  userId: "user123",
  timestamp: new Date(),
  metadata: {
    ip: "192.168.1.1",
    userAgent: "Mozilla/5.0..."
  }
});

Scenario 5: Insert and return complete document

//Insert document
const result = await collection("users").insertOne({
  name: "Alice",
  email: "alice@example.com"
});

//Query the document just inserted (including automatically generated _id)
const newUser = await collection("users").findOne({
  _id: result.insertedId
});

console.log(newUser);
// {
//   _id: ObjectId("..."),
//   name: "Alice",
//   email: "alice@example.com"
// }

Error handling

Duplicate _id

try {
  await collection("users").insertOne({
    _id: "user123",
    name: "Alice"
  });

  //Inserting the same _id again will fail
  await collection("users").insertOne({
    _id: "user123",  //Duplicate _id
    name: "Bob"
  });
} catch (error) {
  if (error.code === ErrorCodes.DUPLICATE_KEY) {
    console.error("Document already exists");
  }
}

Invalid document

try {
  //Error: document must be an object
  await collection("users").insertOne("not an object");
} catch (error) {
  console.error(error.code); // INVALID_ARGUMENT
  console.error(error.message); // "document must be of type object"
}

Unique index conflict

//Assume the email field has a unique index
try {
  await collection("users").insertOne({
    name: "Alice",
    email: "alice@example.com"
  });

  //Inserting the same email will fail
  await collection("users").insertOne({
    name: "Bob",
    email: "alice@example.com"  //Duplicate email
  });
} catch (error) {
  if (error.code === ErrorCodes.DUPLICATE_KEY) {
    console.error("Email has been used");
  }
}

Document verification failed

//Assume that the collection has validation rules
try {
  await collection("users").insertOne({
    name: "Alice"
    //Missing required email field
  });
} catch (error) {
  if (error.code === ErrorCodes.WRITE_ERROR) {
    console.error("Document validation failed:", error.message);
  }
}

Differences from other methods

vs insertMany

FeaturesinsertOneinsertMany
Number of InsertsInsert 1 document at a timeInsert multiple documents at a time
Return valueinsertedId (single)insertedIds (array)
PerformanceLow (individual insert each time)High (batch insert)
AtomicityYes (single document insertion)No (can be partially successful)
Usage ScenariosSingle document creationBatch import of data
//insertOne - single insert
const result1 = await collection("users").insertOne({ name: "Alice" });
console.log(result1.insertedId); // ObjectId

//insertMany - bulk insert
const result2 = await collection("users").insertMany([
  { name: "Bob" },
  { name: "Charlie" }
]);
console.log(result2.insertedIds); // { 0: ObjectId, 1: ObjectId }

vs updateOne with upsert

FeaturesinsertOneupdateOne (upsert: true)
BehaviorOnly insert, fail if it existsInsert if it does not exist, update if it exists
Repeat processingThrow errorUpdate existing document
Usage ScenarioMake sure it is a new documentNot sure if the document exists
//insertOne - fails on duplicate
try {
  await collection("users").insertOne({ _id: "user123", name: "Alice" });
  await collection("users").insertOne({ _id: "user123", name: "Bob" }); //❌ failed
} catch (error) {
  console.error("Document already exists");
}

//updateOne with upsert - update when repeated
await collection("users").updateOne(
  { _id: "user123" },
  { $set: { name: "Alice" } },
  { upsert: true }  //Insert if it does not exist, update if it exists
);

await collection("users").updateOne(
  { _id: "user123" },
  { $set: { name: "Bob" } },
  { upsert: true }  //✅Update successful
);

Performance optimization suggestions

1. Use insertMany when inserting in batches

//Bad: looping call to insertOne
for (const user of users) {
  await collection("users").insertOne(user);  //Slow, one network round trip at a time
}

//Good: use insertMany
await collection("users").insertMany(users);  //Fast, one network round trip

2. Avoid inserting in loops

//Bad: Insert inside loop
const results = [];
for (let i = 0; i < 1000; i++) {
  const result = await collection("items").insertOne({ index: i });
  results.push(result);
}

//Good: prepare data first, then insert in batches
const items = Array.from({ length: 1000 }, (_, i) => ({ index: i }));
const result = await collection("items").insertMany(items);

3. Use appropriate _id type

//ObjectId (default) - 12 bytes, including timestamp
await collection("users").insertOne({ name: "Alice" });

//String - can be used if there is a business ID
await collection("products").insertOne({
  _id: "SKU-12345",  //Business ID
  name: "Laptop"
});

//Number - if there is a serial number
await collection("orders").insertOne({
  _id: 100001,  //Order number
  customerId: "cust123"
});

Best Practices

✅ Contains creation timestamp

await collection("users").insertOne({
  name: "Alice",
  email: "alice@example.com",
  createdAt: new Date(),  //creation time
  updatedAt: new Date()   //Update time
});

✅ Use validation to ensure data quality

//Validate data before inserting
function validateUser(user) {
  if (!user.name || typeof user.name !== "string") {
    throw new Error("name is a required string");
  }
  if (!user.email || !user.email.includes("@")) {
    throw new Error("Invalid email format");
  }
  return true;
}

//Use verification
const newUser = { name: "Alice", email: "alice@example.com" };
if (validateUser(newUser)) {
  await collection("users").insertOne(newUser);
}

✅ Handling duplicate key errors

async function createUser(userData) {
  try {
    const result = await collection("users").insertOne(userData);
    return { success: true, id: result.insertedId };
  } catch (error) {
    if (error.code === ErrorCodes.DUPLICATE_KEY) {
      return { success: false, error: "User already exists" };
    }
    throw error;
  }
}

✅ Use transactions (multiple document insertion)

//If you need to insert into multiple collections atomically
const session = client.startSession();
try {
  await session.withTransaction(async () => {
    //insert user
    const userResult = await collection("users").insertOne(
      { userId: "user123", name: "Alice" },
      { session }
    );

    //Insert user configuration
    await collection("user_settings").insertOne(
      { userId: "user123", theme: "dark" },
      { session }
    );
  });
} finally {
  await session.endSession();
}

Notes

⚠️ _id is immutable

Once inserted, the _id field cannot be modified:

const result = await collection("users").insertOne({
  _id: "user123",
  name: "Alice"
});

//Unable to modify _id
await collection("users").updateOne(
  { _id: "user123" },
  { $set: { _id: "user456" } }  //❌ Error: cannot modify _id
);

⚠️Performance impact of large documents

MongoDB document size is limited to 16MB, but large documents can impact performance:

//Avoid inserting documents that are too large
await collection("files").insertOne({
  name: "large-file.pdf",
  content: Buffer.alloc(15 * 1024 * 1024)  //15MB, close to the limit
});

//Consider using GridFS to store large files

⚠️ Scope of cache invalidation

autoInvalidate: true clears the entire collection's related cache:

//Query and cache
await collection("users").find({ status: "active" }, { cache: 5000 });

//Insert new user and request collection-wide broad invalidation
await collection("users").insertOne(
  { name: "Alice" },
  { autoInvalidate: true }
);

//The cache above is cleared even if the new user's status is not "active"

Utility functions

Safe insertion function (with retry)

/**
 *Insert documents safely (automatic retries)
 */
async function safeInsertOne(collectionName, document, options = {}) {
  const { maxRetries = 3, retryDelay = 100 } = options;

  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const result = await collection(collectionName).insertOne(document);
      return { success: true, insertedId: result.insertedId };
    } catch (error) {
      if (error.code === ErrorCodes.DUPLICATE_KEY) {
        //Repeated keys are not retried
        return { success: false, error: "Document already exists", code: error.code };
      }

      if (attempt < maxRetries) {
        console.warn(`Insert failed (try ${attempt}/${maxRetries}), retry after ${retryDelay}ms...`);
        await new Promise(resolve => setTimeout(resolve, retryDelay));
      } else {
        return { success: false, error: error.message, code: error.code };
      }
    }
  }
}

//Usage example
const result = await safeInsertOne("users", { name: "Alice" });
if (result.success) {
  console.log("Insertion successful:", result.insertedId);
} else {
  console.error("Insertion failed:", result.error);
}
  • insertMany() - Batch insert multiple documents
  • insertBatch() - high-performance batch insertion (batch processing)
  • updateOne() - Update document (insert or update can be achieved with upsert)

Sample code

For complete sample code, please refer to:

MongoDB Documentation