Menu

MongoDB with Node.js: Driver Examples (find, insert, update)

Use MongoDB from Node.js with the official mongodb driver: connect with MongoClient, then insert, find, update and delete documents in a collection, all with async/await.

This page includes runnable editors. Edit, run, and see output instantly.

To use MongoDB from Node.js, install the official driver (npm install mongodb), connect with new MongoClient(uri), pick a database with client.db('name') and a collection with db.collection('name'). Every operation (insertOne, find, updateOne, deleteOne) returns a promise, so you await it. Documents go in and come out as plain JavaScript objects.

It prints [ 'Dune', 'Neuromancer', 'Hyperion' ]. The shop database and books collection did not exist before: MongoDB creates them on the first insert, and toArray() loads every document the find() cursor points to.

Find documents with filters and projection

A filter is an object describing the documents you want. Plain values match exactly; operators such as $gt, $lt, $in and $regex go in a nested object. The second argument's projection picks which fields come back.

recent holds the two newest books after 1960, Hyperion then Neuromancer, with only title and year; findOne returns the first match (or null), and countDocuments counts 2 books costing 10 or more. Change $gt: 1960 to $gt: 1985 and only Hyperion is left.

Update and delete

updateOne(filter, update) changes the first matching document. The update uses operators: $set replaces fields, $inc adds to a number, $unset removes a field and $push appends to an array. updateMany and deleteMany work on every match.

The update matched and modified one document, so Dune now costs 10 with 2 in stock, and deleting the book with no stock leaves 1. An update must use operators: pass { price: 10 } without $set and the driver refuses it (replaceOne is the call that replaces a whole document).

ObjectId and indexes

Every document gets an _id; when you do not set one, the driver creates an ObjectId. To find a document by an id that arrived as a string (from a URL, say), wrap it in new ObjectId(id). An index makes a field fast to search, and a unique index makes MongoDB refuse duplicates.

An ObjectId is 24 hex characters as a string, and searching with the plain string finds nothing, so that line prints null. The second insert breaks the unique index and fails with code 11000, which is how you detect "email already taken".

Use MongoDB in an Express API

Connect once when the server starts and share the collection; do not open a new connection per request. The driver keeps a pool of connections and reuses them.

GET /books returns both books, each with an _id. Copy one id into GET /books/<id> to fetch a single book, or send POST /books with a JSON body like {"title": "Foundation", "year": 1951} and list the books again.

A real app reads the connection string from process.env.MONGODB_URI instead of writing it in the code.

If you want schemas and validation on top of the driver, Mongoose (npm install mongoose) wraps it:

const Book = mongoose.model('Book', new mongoose.Schema({ title: String, year: Number }));
await Book.create({ title: 'Dune', year: 1965 });

Common mistakes

Forgetting toArray(). find() returns a cursor, not documents. Logging it shows a cursor object; call toArray(), or loop over it with for await.

Connecting on every request. Each new MongoClient opens its own pool. Create one client at startup and reuse it everywhere.

Never closing the client in a script. An open client keeps the process alive after your code is done. Call await client.close() at the end of scripts; a server keeps it open for its whole life.

Frequently Asked Questions

Should I use the mongodb driver or Mongoose?

The driver is the official, thinner layer: you work with plain objects and MongoDB's own query language. Mongoose adds schemas, validation and models on top of it, which helps when you want every document checked. Both talk to the same database, and Mongoose uses the driver underneath.

Do I need to create a database or collection first?

No. MongoDB creates both the first time you insert a document into them. client.db('shop') and db.collection('books') only return handles.

Where do I put the connection string?

In an environment variable such as MONGODB_URI, read with process.env.MONGODB_URI. A hosted database's string contains a password, so it must never be committed to the repository.

Why does find return no documents when I search by id?

_id is stored as an ObjectId, not a string, so { _id: '65f1...' } matches nothing. Convert it first: { _id: new ObjectId(id) }.

Coddy programming languages illustration

Learn to code with Coddy

Get started