R
Rishtaara
MongoDB Fundamentals
Lesson 16 of 40Article16 min

Query Nested Docs, Arrays & Null

Documents can contain nested objects. Use dot notation to query nested fields — "address.city" matches the city inside an address object.

Embedded and nested documents — dot notation

Documents can contain nested objects. Use dot notation to query nested fields — "address.city" matches the city inside an address object.

Real-life example: Dot notation is like writing 'home address → city' on a form — you drill into a nested level to find the value.

Query nested fields
// Sample student document:
// {
//   name: "Rahul Sharma",
//   address: { city: "Bengaluru", pincode: "560001", state: "Karnataka" },
//   guardian: { name: "Mr. Sharma", phone: "9876543210" }
// }

// Students in Bengaluru
db.students.find({ "address.city": "Bengaluru" })

// Students in Karnataka with pincode starting 560
db.students.find({
  "address.state": "Karnataka",
  "address.pincode": { $regex: "^560" }
})

// Products with supplier in a specific region
db.products.find({ "supplier.country": "IN" })

Query arrays — $all, $size, $elemMatch

Arrays store ordered lists. Equality on an array field matches if any element equals the value. Use $all, $size, and $elemMatch for precise array queries.

Real-life example: Querying arrays is like asking 'students who take BOTH Math AND CS' ($all) vs 'students who take Math' (any element match).

$elemMatch is required when multiple conditions must apply to the same array element. Without it, MongoDB may match conditions on different elements.
Basic array queries
// Any student with Mathematics as a subject
db.students.find({ subjects: "Mathematics" })

// $all — document must contain ALL listed values
db.students.find({
  subjects: { $all: ["Mathematics", "Computer Science"] }
})

// $size — array must have exactly N elements
db.products.find({ tags: { $size: 3 } })

// $elemMatch — at least one array element matches ALL conditions
db.orders.find({
  items: {
    $elemMatch: { productName: "Mouse", qty: { $gte: 2 } }
  }
})

// Match array of embedded documents
db.students.find({
  scores: {
    $elemMatch: { subject: "Physics", marks: { $gte: 90 } }
  }
})
Array position and nested arrays
// First element of array (zero-indexed)
db.students.find({ "subjects.0": "Mathematics" })

// Nested array in order items
db.orders.find({ "items.0.category": "electronics" })

// $size does not accept ranges — use $expr for "more than 3 tags"
db.products.find({
  $expr: { $gt: [{ $size: { $ifNull: ["$tags", []] } }, 3] }
})

Null and missing fields — $exists

In MongoDB, null and missing fields behave differently. { field: null } matches documents where field is null OR field does not exist. Use $exists to distinguish.

Real-life example: $exists is like asking 'Does this form have an email field filled in?' vs 'Is the email blank?' — different questions.

  • Use $exists: false in read queries when implementing soft delete filters.
  • Schema validation can require fields — but legacy data may still lack them.
  • Combine $exists with $type to find fields of unexpected types.
null vs missing with $exists
// Matches: field is null OR field is absent
db.students.find({ email: null })

// Field exists (any value including null)
db.students.find({ email: { $exists: true } })

// Field is completely absent
db.students.find({ email: { $exists: false } })

// Field exists AND is explicitly null (not missing)
db.students.find({
  email: { $exists: true, $eq: null }
})

// Students missing phone number
db.students.find({ phone: { $exists: false } })

// Products with no discount field (never on sale)
db.products.find({ discount: { $exists: false } })
Practical audit queries
// Find incomplete student profiles
db.students.find({
  $or: [
    { email: { $exists: false } },
    { email: null },
    { email: "" }
  ]
})

// Products missing required category
db.products.find({ category: { $exists: false } })

// Count how many users have no profile photo
db.users.countDocuments({ profilePhotoUrl: { $exists: false } })