MongoDB Find

The find() and findOne() methods are how you read documents back out of a MongoDB collection, and mastering their filter syntax is the foundation for everything else you'll do with queries.

Reading Documents with find()

Every read operation in MongoDB starts with db.collection.find(). Called with no arguments, it returns a cursor over every document in the collection. Called with a query filter as its first argument, it returns only the documents that match. Unlike a relational SELECT, there is no separate query language to learn — filters are just JSON documents describing the shape of the data you want back.

Return every document in a collection

db.products.find()

// Equivalent, explicit empty filter
db.products.find({})

Filtering with Field Equality

The simplest filter matches a field against an exact value. { field: value } tells MongoDB to return only documents where that field equals value. You can combine several fields in the same filter object; by default MongoDB treats multiple fields as an implicit AND, so every condition must be true for a document to match.

Filter by one and by several fields

// Single-field equality
db.products.find({ category: 'electronics' })

// Multiple fields (implicit AND)
db.products.find({
  category: 'electronics',
  inStock: true
})

findOne() vs find()

find() always returns a cursor, even when only one document matches — you have to iterate it (or call .toArray() in the shell) to see the data. findOne() skips the cursor entirely and hands back a single document object directly, or null if nothing matched. Reach for findOne() whenever your application logic only ever needs the first match, such as looking up a user by a unique email address.

findOne returns a single document, not a cursor

// Returns the first matching document, or null
const user = db.users.findOne({ email: 'ada@example.com' })

// Returns a cursor you must iterate
db.users.find({ email: 'ada@example.com' }).forEach(doc => {
  print(doc.name)
})

Projections: Choosing Which Fields Come Back

Both find() and findOne() accept a second argument called a projection. It's a document that lists which fields to include (1) or exclude (0). The _id field is included automatically unless you explicitly set _id: 0. Projections reduce network traffic and keep your application code from accidentally depending on fields it doesn't need.

  • { field: 1 } — include only this field (plus _id)
  • { field: 0 } — include everything except this field
  • You cannot mix 1s and 0s in the same projection, except alongside _id: 0
  • Projections do not filter documents — they only shape which fields appear

Shape the returned fields with a projection

// Only return name and price (plus _id)
db.products.find(
  { category: 'electronics' },
  { name: 1, price: 1 }
)

// Return everything except the internal notes field
db.products.find(
  { category: 'electronics' },
  { internalNotes: 0 }
)
Note: Cursors returned by find() are lazy — MongoDB doesn't actually pull documents from the server until you start iterating (or chain something like .toArray()), so it's cheap to build up a cursor and add .sort() or .limit() before executing it.
Note: Heads up: findOne() with no matching filter returns null, not an empty object or an error — always guard against null before reading properties off the result in your application code.
MethodReturnsTypical use
find(filter)Cursor (0 or more docs)Listing, iterating, paging
find(filter, projection)Cursor with shaped fieldsListing with fewer fields
findOne(filter)A single document or nullLookup by unique key
find().sort()/.limit()Cursor, chainedTop-N, pagination

Exercise: MongoDB Find

What does db.collection.find() actually return?