MongoDB's query language (MQL) provides a rich set of operators for filtering, comparing, and searching documents. This lesson covers all major query operators with real examples using a products and users dataset.
// $eq — explicit (usually you just write the value directly)
db.products.find({ category: { $eq: "electronics" } })
db.products.find({ category: "electronics" }) // same thing, shorthand// $ne — not equal
db.products.find({ category: { $ne: "furniture" } })
// $gt / $gte / $lt / $lte — ranges
db.products.find({ price: { $gt: 100 } }) // price > 100
db.products.find({ price: { $gte: 100, $lte: 500 } }) // 100 <= price <= 500
db.products.find({ stock: { $gt: 0 } }) // in stock// Works on dates too
db.orders.find({
createdAt: {
$gte: newDate("2024-01-01"),
$lt: newDate("2024-02-01")
}
})
// $in — match one of many values
db.products.find({ category: { $in: ["electronics", "furniture"] } })
db.products.find({ rating: { $in: [4.5, 4.6, 4.7] } })
// $nin — match none of these values
db.products.find({ category: { $nin: ["furniture", "clothing"] } })
2. Logical Operators
// $and — all conditions must be true (implicit AND by default)
db.products.find({
$and: [
{ category: "electronics" },
{ price: { $lt: 100 } },
{ active: true }
]
})
// Same as (implicit AND):
db.products.find({ category: "electronics", price: { $lt: 100 }, active: true })
// Explicit $and is needed when using same field twice
db.products.find({
$and: [
{ price: { $gte: 50 } },
{ price: { $lte: 500 } }
]
})
// $or — at least one condition must be true
db.products.find({
$or: [
{ price: { $lt: 50 } },
{ category: "furniture" }
]
})
// Combine $and and $or
db.products.find({
active: true,
$or: [
{ price: { $lt: 100 } },
{ rating: { $gte: 4.5 } }
]
})
// $nor — none of the conditions must be true
db.products.find({
$nor: [
{ category: "furniture" },
{ price: { $gt: 1000 } }
]
})
// Returns products that are NOT furniture AND NOT over $1000// $not — negates a single condition
db.products.find({ price: { $not: { $gt: 500 } } }) // price NOT > 500
db.products.find({ name: { $not: /Laptop/i } }) // name does NOT match regex
3. Element Operators
// $exists — check if a field exists (or doesn't exist)
db.products.find({ discount: { $exists: true } }) // has a discount field
db.products.find({ discount: { $exists: false } }) // no discount field// $exists: true also matches null values// Use with $ne to exclude null:
db.products.find({ discount: { $exists: true, $ne: null } })
// $type — filter by BSON type
db.products.find({ price: { $type: "double" } }) // price is a float
db.products.find({ price: { $type: "int" } }) // price is an integer
db.products.find({ name: { $type: "string" } }) // name is a string
db.products.find({ _id: { $type: "objectId" } }) // _id is ObjectId
db.products.find({ tags: { $type: "array" } }) // tags field is an array// $type with multiple types
db.mixed.find({ value: { $type: ["string", "double"] } })
4. Array Operators
// Match documents where array contains a value
db.products.find({ tags: "wireless" }) // tags array includes "wireless"// $all — array must contain ALL specified values
db.products.find({ tags: { $all: ["office", "ergonomic"] } })
// returns docs where tags contains BOTH "office" AND "ergonomic"// $size — array has exact number of elements
db.products.find({ tags: { $size: 2 } }) // exactly 2 tags// $elemMatch — at least one element matches ALL conditions
db.orders.find({
items: {
$elemMatch: {
price: { $gt: 100 },
quantity: { $gte: 2 }
}
}
})
// Finds orders where a single item has price > 100 AND quantity >= 2// Without $elemMatch (wrong — applies conditions across elements)
db.orders.find({
"items.price": { $gt: 100 },
"items.quantity": { $gte: 2 }
})
// This could match if different items satisfy each condition!// Query array element by position
db.products.find({ "tags.0": "computer" }) // first tag is "computer"
5. Evaluation Operators
$regex — Pattern Matching
// Case-insensitive search for "laptop" in name
db.products.find({ name: { $regex: "laptop", $options: "i" } })
// Inline regex literal
db.products.find({ name: /^Wireless/i }) // starts with "Wireless"
db.products.find({ name: /Hub$/ }) // ends with "Hub"
db.products.find({ category: /electron/i }) // contains "electron"// Regex options:// i - case insensitive// m - multiline (^ and $ match line boundaries)// x - extended (ignore whitespace)// s - allows . to match newlines
$text — Full-Text Search
// First: create a text index on the fields to search
db.products.createIndex({ name: "text", description: "text" })
// Then: use $text to search
db.products.find({ $text: { $search: "laptop computer" } })
// Exact phrase search (use quotes)
db.products.find({ $text: { $search: "\"standing desk\"" } })
// Exclude word (prefix with -)
db.products.find({ $text: { $search: "desk -chair" } })
// Sort by text relevance score
db.products.find(
{ $text: { $search: "wireless" } },
{ score: { $meta: "textScore" } }
).sort({ score: { $meta: "textScore" } })
$expr — Use Aggregation Expressions in Queries
// Find products where discountedPrice < originalPrice * 0.8
db.products.find({
$expr: { $lt: ["$discountedPrice", { $multiply: ["$price", 0.8] }] }
})
// Compare two fields in the same document
db.orders.find({
$expr: { $gt: ["$total", "$budget"] }
})
// Finds orders where total exceeds the customer's budget